1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petsc/private/isimpl.h> 3 #include <petsc/private/vecimpl.h> 4 #include <petsc/private/glvisvecimpl.h> 5 #include <petscsf.h> 6 #include <petscds.h> 7 #include <petscdraw.h> 8 #include <petscdmfield.h> 9 #include <petscdmplextransform.h> 10 11 /* Logging support */ 12 PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF,DMPLEX_LocatePoints,DMPLEX_TopologyView,DMPLEX_LabelsView,DMPLEX_CoordinatesView,DMPLEX_SectionView,DMPLEX_GlobalVectorView,DMPLEX_LocalVectorView,DMPLEX_TopologyLoad,DMPLEX_LabelsLoad,DMPLEX_CoordinatesLoad,DMPLEX_SectionLoad,DMPLEX_GlobalVectorLoad,DMPLEX_LocalVectorLoad; 13 14 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 15 16 /*@ 17 DMPlexIsSimplex - Is the first cell in this mesh a simplex? 18 19 Input Parameter: 20 . dm - The DMPlex object 21 22 Output Parameter: 23 . simplex - Flag checking for a simplex 24 25 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 26 If the mesh has no cells, this returns PETSC_FALSE. 27 28 Level: intermediate 29 30 .seealso DMPlexGetSimplexOrBoxCells(), DMPlexGetCellType(), DMPlexGetHeightStratum(), DMPolytopeTypeGetNumVertices() 31 @*/ 32 PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 33 { 34 DMPolytopeType ct; 35 PetscInt cStart, cEnd; 36 PetscErrorCode ierr; 37 38 PetscFunctionBegin; 39 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 40 if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);} 41 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 42 *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 43 PetscFunctionReturn(0); 44 } 45 46 /*@ 47 DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 48 49 Input Parameters: 50 + dm - The DMPlex object 51 - height - The cell height in the Plex, 0 is the default 52 53 Output Parameters: 54 + cStart - The first "normal" cell 55 - cEnd - The upper bound on "normal"" cells 56 57 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 58 59 Level: developer 60 61 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 62 @*/ 63 PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 64 { 65 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 66 PetscInt cS, cE, c; 67 PetscErrorCode ierr; 68 69 PetscFunctionBegin; 70 ierr = DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE);CHKERRQ(ierr); 71 for (c = cS; c < cE; ++c) { 72 DMPolytopeType cct; 73 74 ierr = DMPlexGetCellType(dm, c, &cct);CHKERRQ(ierr); 75 if ((PetscInt) cct < 0) break; 76 switch (cct) { 77 case DM_POLYTOPE_POINT: 78 case DM_POLYTOPE_SEGMENT: 79 case DM_POLYTOPE_TRIANGLE: 80 case DM_POLYTOPE_QUADRILATERAL: 81 case DM_POLYTOPE_TETRAHEDRON: 82 case DM_POLYTOPE_HEXAHEDRON: 83 ct = cct; 84 break; 85 default: break; 86 } 87 if (ct != DM_POLYTOPE_UNKNOWN) break; 88 } 89 if (ct != DM_POLYTOPE_UNKNOWN) { 90 DMLabel ctLabel; 91 92 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 93 ierr = DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE);CHKERRQ(ierr); 94 } 95 if (cStart) *cStart = cS; 96 if (cEnd) *cEnd = cE; 97 PetscFunctionReturn(0); 98 } 99 100 PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 101 { 102 PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 103 PetscInt vcdof[2] = {0,0}, globalvcdof[2]; 104 PetscErrorCode ierr; 105 106 PetscFunctionBegin; 107 *ft = PETSC_VTK_INVALID; 108 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 109 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 110 ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 111 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 112 if (field >= 0) { 113 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]);CHKERRQ(ierr);} 114 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]);CHKERRQ(ierr);} 115 } else { 116 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vcdof[0]);CHKERRQ(ierr);} 117 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &vcdof[1]);CHKERRQ(ierr);} 118 } 119 ierr = MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 120 if (globalvcdof[0]) { 121 *sStart = vStart; 122 *sEnd = vEnd; 123 if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 124 else *ft = PETSC_VTK_POINT_FIELD; 125 } else if (globalvcdof[1]) { 126 *sStart = cStart; 127 *sEnd = cEnd; 128 if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 129 else *ft = PETSC_VTK_CELL_FIELD; 130 } else { 131 if (field >= 0) { 132 const char *fieldname; 133 134 ierr = PetscSectionGetFieldName(section, field, &fieldname);CHKERRQ(ierr); 135 ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname);CHKERRQ(ierr); 136 } else { 137 ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\"%s\"\n");CHKERRQ(ierr); 138 } 139 } 140 PetscFunctionReturn(0); 141 } 142 143 static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 144 { 145 DM dm; 146 PetscSection s; 147 PetscDraw draw, popup; 148 DM cdm; 149 PetscSection coordSection; 150 Vec coordinates; 151 const PetscScalar *coords, *array; 152 PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 153 PetscReal vbound[2], time; 154 PetscBool isnull, flg; 155 PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 156 const char *name; 157 char title[PETSC_MAX_PATH_LEN]; 158 PetscErrorCode ierr; 159 160 PetscFunctionBegin; 161 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 162 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 163 if (isnull) PetscFunctionReturn(0); 164 165 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 166 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 167 PetscCheckFalse(dim != 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D. Use PETSCVIEWERGLVIS", dim); 168 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 169 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 170 ierr = DMGetCoarsenLevel(dm, &level);CHKERRQ(ierr); 171 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 172 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 173 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 174 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 175 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 176 177 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 178 ierr = DMGetOutputSequenceNumber(dm, &step, &time);CHKERRQ(ierr); 179 180 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 181 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 182 for (c = 0; c < N; c += dim) { 183 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 184 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 185 } 186 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 187 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 188 189 /* Could implement something like DMDASelectFields() */ 190 for (f = 0; f < Nf; ++f) { 191 DM fdm = dm; 192 Vec fv = v; 193 IS fis; 194 char prefix[PETSC_MAX_PATH_LEN]; 195 const char *fname; 196 197 ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr); 198 ierr = PetscSectionGetFieldName(s, f, &fname);CHKERRQ(ierr); 199 200 if (v->hdr.prefix) {ierr = PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix));CHKERRQ(ierr);} 201 else {prefix[0] = '\0';} 202 if (Nf > 1) { 203 ierr = DMCreateSubDM(dm, 1, &f, &fis, &fdm);CHKERRQ(ierr); 204 ierr = VecGetSubVector(v, fis, &fv);CHKERRQ(ierr); 205 ierr = PetscStrlcat(prefix, fname,sizeof(prefix));CHKERRQ(ierr); 206 ierr = PetscStrlcat(prefix, "_",sizeof(prefix));CHKERRQ(ierr); 207 } 208 for (comp = 0; comp < Nc; ++comp, ++w) { 209 PetscInt nmax = 2; 210 211 ierr = PetscViewerDrawGetDraw(viewer, w, &draw);CHKERRQ(ierr); 212 if (Nc > 1) {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time);CHKERRQ(ierr);} 213 else {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time);CHKERRQ(ierr);} 214 ierr = PetscDrawSetTitle(draw, title);CHKERRQ(ierr); 215 216 /* TODO Get max and min only for this component */ 217 ierr = PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg);CHKERRQ(ierr); 218 if (!flg) { 219 ierr = VecMin(fv, NULL, &vbound[0]);CHKERRQ(ierr); 220 ierr = VecMax(fv, NULL, &vbound[1]);CHKERRQ(ierr); 221 if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 222 } 223 ierr = PetscDrawGetPopup(draw, &popup);CHKERRQ(ierr); 224 ierr = PetscDrawScalePopup(popup, vbound[0], vbound[1]);CHKERRQ(ierr); 225 ierr = PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]);CHKERRQ(ierr); 226 227 ierr = VecGetArrayRead(fv, &array);CHKERRQ(ierr); 228 for (c = cStart; c < cEnd; ++c) { 229 PetscScalar *coords = NULL, *a = NULL; 230 PetscInt numCoords, color[4] = {-1,-1,-1,-1}; 231 232 ierr = DMPlexPointLocalRead(fdm, c, array, &a);CHKERRQ(ierr); 233 if (a) { 234 color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 235 color[1] = color[2] = color[3] = color[0]; 236 } else { 237 PetscScalar *vals = NULL; 238 PetscInt numVals, va; 239 240 ierr = DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 241 PetscCheckFalse(numVals % Nc,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %D does not divide the number of values in the closure %D", Nc, numVals); 242 switch (numVals/Nc) { 243 case 3: /* P1 Triangle */ 244 case 4: /* P1 Quadrangle */ 245 for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]); 246 break; 247 case 6: /* P2 Triangle */ 248 case 8: /* P2 Quadrangle */ 249 for (va = 0; va < numVals/(Nc*2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp + numVals/(Nc*2)]), vbound[0], vbound[1]); 250 break; 251 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc); 252 } 253 ierr = DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 254 } 255 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 256 switch (numCoords) { 257 case 6: 258 case 12: /* Localized triangle */ 259 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 260 break; 261 case 8: 262 case 16: /* Localized quadrilateral */ 263 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 264 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0]);CHKERRQ(ierr); 265 break; 266 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords); 267 } 268 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 269 } 270 ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr); 271 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 272 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 273 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 274 } 275 if (Nf > 1) { 276 ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr); 277 ierr = ISDestroy(&fis);CHKERRQ(ierr); 278 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 279 } 280 } 281 PetscFunctionReturn(0); 282 } 283 284 static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 285 { 286 DM dm; 287 Vec locv; 288 const char *name; 289 PetscSection section; 290 PetscInt pStart, pEnd; 291 PetscInt numFields; 292 PetscViewerVTKFieldType ft; 293 PetscErrorCode ierr; 294 295 PetscFunctionBegin; 296 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 297 ierr = DMCreateLocalVector(dm, &locv);CHKERRQ(ierr); /* VTK viewer requires exclusive ownership of the vector */ 298 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 299 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 300 ierr = VecCopy(v, locv);CHKERRQ(ierr); 301 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 302 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 303 if (!numFields) { 304 ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 305 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 306 } else { 307 PetscInt f; 308 309 for (f = 0; f < numFields; f++) { 310 ierr = DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft);CHKERRQ(ierr); 311 if (ft == PETSC_VTK_INVALID) continue; 312 ierr = PetscObjectReference((PetscObject)locv);CHKERRQ(ierr); 313 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 314 } 315 ierr = VecDestroy(&locv);CHKERRQ(ierr); 316 } 317 PetscFunctionReturn(0); 318 } 319 320 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 321 { 322 DM dm; 323 PetscBool isvtk, ishdf5, isdraw, isglvis; 324 PetscErrorCode ierr; 325 326 PetscFunctionBegin; 327 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 328 PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 329 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 330 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 331 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 332 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 333 if (isvtk || ishdf5 || isdraw || isglvis) { 334 PetscInt i,numFields; 335 PetscObject fe; 336 PetscBool fem = PETSC_FALSE; 337 Vec locv = v; 338 const char *name; 339 PetscInt step; 340 PetscReal time; 341 342 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 343 for (i=0; i<numFields; i++) { 344 ierr = DMGetField(dm, i, NULL, &fe);CHKERRQ(ierr); 345 if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; } 346 } 347 if (fem) { 348 PetscObject isZero; 349 350 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 351 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 352 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 353 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 354 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 355 ierr = VecCopy(v, locv);CHKERRQ(ierr); 356 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 357 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr); 358 } 359 if (isvtk) { 360 ierr = VecView_Plex_Local_VTK(locv, viewer);CHKERRQ(ierr); 361 } else if (ishdf5) { 362 #if defined(PETSC_HAVE_HDF5) 363 ierr = VecView_Plex_Local_HDF5_Internal(locv, viewer);CHKERRQ(ierr); 364 #else 365 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 366 #endif 367 } else if (isdraw) { 368 ierr = VecView_Plex_Local_Draw(locv, viewer);CHKERRQ(ierr); 369 } else if (isglvis) { 370 ierr = DMGetOutputSequenceNumber(dm, &step, NULL);CHKERRQ(ierr); 371 ierr = PetscViewerGLVisSetSnapId(viewer, step);CHKERRQ(ierr); 372 ierr = VecView_GLVis(locv, viewer);CHKERRQ(ierr); 373 } 374 if (fem) { 375 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 376 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 377 } 378 } else { 379 PetscBool isseq; 380 381 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 382 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 383 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 384 } 385 PetscFunctionReturn(0); 386 } 387 388 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 389 { 390 DM dm; 391 PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii; 392 PetscErrorCode ierr; 393 394 PetscFunctionBegin; 395 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 396 PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 397 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 398 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 399 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 400 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 401 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 402 if (isvtk || isdraw || isglvis) { 403 Vec locv; 404 PetscObject isZero; 405 const char *name; 406 407 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 408 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 409 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 410 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 411 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 412 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 413 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 414 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 415 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 416 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 417 } else if (ishdf5) { 418 #if defined(PETSC_HAVE_HDF5) 419 ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 420 #else 421 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 422 #endif 423 } else if (isexodusii) { 424 #if defined(PETSC_HAVE_EXODUSII) 425 ierr = VecView_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 426 #else 427 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 428 #endif 429 } else { 430 PetscBool isseq; 431 432 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 433 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 434 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 435 } 436 PetscFunctionReturn(0); 437 } 438 439 PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 440 { 441 DM dm; 442 MPI_Comm comm; 443 PetscViewerFormat format; 444 Vec v; 445 PetscBool isvtk, ishdf5; 446 PetscErrorCode ierr; 447 448 PetscFunctionBegin; 449 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 450 ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 451 PetscCheckFalse(!dm,comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 452 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 453 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 454 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 455 if (format == PETSC_VIEWER_NATIVE) { 456 /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 457 /* this need a better fix */ 458 if (dm->useNatural) { 459 if (dm->sfNatural) { 460 const char *vecname; 461 PetscInt n, nroots; 462 463 ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr); 464 ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 465 if (n == nroots) { 466 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 467 ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 468 ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 469 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 470 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 471 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 472 } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 473 } else v = originalv; 474 } else v = originalv; 475 476 if (ishdf5) { 477 #if defined(PETSC_HAVE_HDF5) 478 ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 479 #else 480 SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 481 #endif 482 } else if (isvtk) { 483 SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 484 } else { 485 PetscBool isseq; 486 487 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 488 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 489 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 490 } 491 if (v != originalv) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 492 PetscFunctionReturn(0); 493 } 494 495 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 496 { 497 DM dm; 498 PetscBool ishdf5; 499 PetscErrorCode ierr; 500 501 PetscFunctionBegin; 502 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 503 PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 504 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 505 if (ishdf5) { 506 DM dmBC; 507 Vec gv; 508 const char *name; 509 510 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 511 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 512 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 513 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 514 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 515 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 516 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 517 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 518 } else { 519 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 520 } 521 PetscFunctionReturn(0); 522 } 523 524 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 525 { 526 DM dm; 527 PetscBool ishdf5,isexodusii; 528 PetscErrorCode ierr; 529 530 PetscFunctionBegin; 531 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 532 PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 533 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 534 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 535 if (ishdf5) { 536 #if defined(PETSC_HAVE_HDF5) 537 ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 538 #else 539 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 540 #endif 541 } else if (isexodusii) { 542 #if defined(PETSC_HAVE_EXODUSII) 543 ierr = VecLoad_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 544 #else 545 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 546 #endif 547 } else { 548 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 549 } 550 PetscFunctionReturn(0); 551 } 552 553 PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 554 { 555 DM dm; 556 PetscViewerFormat format; 557 PetscBool ishdf5; 558 PetscErrorCode ierr; 559 560 PetscFunctionBegin; 561 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 562 PetscCheckFalse(!dm,PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 563 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 564 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 565 if (format == PETSC_VIEWER_NATIVE) { 566 if (dm->useNatural) { 567 if (dm->sfNatural) { 568 if (ishdf5) { 569 #if defined(PETSC_HAVE_HDF5) 570 Vec v; 571 const char *vecname; 572 573 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 574 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 575 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 576 ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 577 ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 578 ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 579 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 580 #else 581 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 582 #endif 583 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 584 } 585 } else { 586 ierr = VecLoad_Default(originalv, viewer);CHKERRQ(ierr); 587 } 588 } 589 PetscFunctionReturn(0); 590 } 591 592 PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 593 { 594 PetscSection coordSection; 595 Vec coordinates; 596 DMLabel depthLabel, celltypeLabel; 597 const char *name[4]; 598 const PetscScalar *a; 599 PetscInt dim, pStart, pEnd, cStart, cEnd, c; 600 PetscErrorCode ierr; 601 602 PetscFunctionBegin; 603 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 604 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 605 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 606 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 607 ierr = DMPlexGetCellTypeLabel(dm, &celltypeLabel);CHKERRQ(ierr); 608 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 609 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 610 ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 611 name[0] = "vertex"; 612 name[1] = "edge"; 613 name[dim-1] = "face"; 614 name[dim] = "cell"; 615 for (c = cStart; c < cEnd; ++c) { 616 PetscInt *closure = NULL; 617 PetscInt closureSize, cl, ct; 618 619 ierr = DMLabelGetValue(celltypeLabel, c, &ct);CHKERRQ(ierr); 620 ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]);CHKERRQ(ierr); 621 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 622 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 623 for (cl = 0; cl < closureSize*2; cl += 2) { 624 PetscInt point = closure[cl], depth, dof, off, d, p; 625 626 if ((point < pStart) || (point >= pEnd)) continue; 627 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 628 if (!dof) continue; 629 ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 630 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 631 ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr); 632 for (p = 0; p < dof/dim; ++p) { 633 ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 634 for (d = 0; d < dim; ++d) { 635 if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 636 ierr = PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 637 } 638 ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 639 } 640 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 641 } 642 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 643 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 644 } 645 ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 646 PetscFunctionReturn(0); 647 } 648 649 typedef enum {CS_CARTESIAN, CS_POLAR, CS_CYLINDRICAL, CS_SPHERICAL} CoordSystem; 650 const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 651 652 static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 653 { 654 PetscInt i; 655 PetscErrorCode ierr; 656 657 PetscFunctionBegin; 658 if (dim > 3) { 659 for (i = 0; i < dim; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) PetscRealPart(x[i]));CHKERRQ(ierr);} 660 } else { 661 PetscReal coords[3], trcoords[3]; 662 663 for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 664 switch (cs) { 665 case CS_CARTESIAN: for (i = 0; i < dim; ++i) trcoords[i] = coords[i];break; 666 case CS_POLAR: 667 PetscCheckFalse(dim != 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %D", dim); 668 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 669 trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 670 break; 671 case CS_CYLINDRICAL: 672 PetscCheckFalse(dim != 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %D", dim); 673 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 674 trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 675 trcoords[2] = coords[2]; 676 break; 677 case CS_SPHERICAL: 678 PetscCheckFalse(dim != 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %D", dim); 679 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 680 trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 681 trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 682 break; 683 } 684 for (i = 0; i < dim; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) trcoords[i]);CHKERRQ(ierr);} 685 } 686 PetscFunctionReturn(0); 687 } 688 689 static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 690 { 691 DM_Plex *mesh = (DM_Plex*) dm->data; 692 DM cdm; 693 PetscSection coordSection; 694 Vec coordinates; 695 PetscViewerFormat format; 696 PetscErrorCode ierr; 697 698 PetscFunctionBegin; 699 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 700 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 701 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 702 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 703 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 704 const char *name; 705 PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 706 PetscInt pStart, pEnd, p, numLabels, l; 707 PetscMPIInt rank, size; 708 709 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 710 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 711 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 712 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 713 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 714 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 715 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 716 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 717 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 718 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 719 ierr = PetscViewerASCIIPrintf(viewer, "Supports:\n", name);CHKERRQ(ierr); 720 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 721 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize);CHKERRQ(ierr); 722 for (p = pStart; p < pEnd; ++p) { 723 PetscInt dof, off, s; 724 725 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 726 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 727 for (s = off; s < off+dof; ++s) { 728 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 729 } 730 } 731 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 732 ierr = PetscViewerASCIIPrintf(viewer, "Cones:\n", name);CHKERRQ(ierr); 733 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize);CHKERRQ(ierr); 734 for (p = pStart; p < pEnd; ++p) { 735 PetscInt dof, off, c; 736 737 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 738 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 739 for (c = off; c < off+dof; ++c) { 740 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 741 } 742 } 743 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 744 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 745 if (coordSection && coordinates) { 746 CoordSystem cs = CS_CARTESIAN; 747 const PetscScalar *array; 748 PetscInt Nf, Nc, pStart, pEnd, p; 749 PetscMPIInt rank; 750 const char *name; 751 752 ierr = PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL);CHKERRQ(ierr); 753 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRMPI(ierr); 754 ierr = PetscSectionGetNumFields(coordSection, &Nf);CHKERRQ(ierr); 755 PetscCheckFalse(Nf != 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %D", Nf); 756 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 757 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 758 ierr = PetscObjectGetName((PetscObject) coordinates, &name);CHKERRQ(ierr); 759 ierr = PetscViewerASCIIPrintf(viewer, "%s with %D fields\n", name, Nf);CHKERRQ(ierr); 760 ierr = PetscViewerASCIIPrintf(viewer, " field 0 with %D components\n", Nc);CHKERRQ(ierr); 761 if (cs != CS_CARTESIAN) {ierr = PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs]);CHKERRQ(ierr);} 762 763 ierr = VecGetArrayRead(coordinates, &array);CHKERRQ(ierr); 764 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 765 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank);CHKERRQ(ierr); 766 for (p = pStart; p < pEnd; ++p) { 767 PetscInt dof, off; 768 769 ierr = PetscSectionGetDof(coordSection, p, &dof);CHKERRQ(ierr); 770 ierr = PetscSectionGetOffset(coordSection, p, &off);CHKERRQ(ierr); 771 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " (%4D) dim %2D offset %3D", p, dof, off);CHKERRQ(ierr); 772 ierr = DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]);CHKERRQ(ierr); 773 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\n");CHKERRQ(ierr); 774 } 775 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 776 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 777 ierr = VecRestoreArrayRead(coordinates, &array);CHKERRQ(ierr); 778 } 779 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 780 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 781 for (l = 0; l < numLabels; ++l) { 782 DMLabel label; 783 PetscBool isdepth; 784 const char *name; 785 786 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 787 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 788 if (isdepth) continue; 789 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 790 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 791 } 792 if (size > 1) { 793 PetscSF sf; 794 795 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 796 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 797 } 798 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 799 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 800 const char *name, *color; 801 const char *defcolors[3] = {"gray", "orange", "green"}; 802 const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 803 char lname[PETSC_MAX_PATH_LEN]; 804 PetscReal scale = 2.0; 805 PetscReal tikzscale = 1.0; 806 PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 807 double tcoords[3]; 808 PetscScalar *coords; 809 PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 810 PetscMPIInt rank, size; 811 char **names, **colors, **lcolors; 812 PetscBool flg, lflg; 813 PetscBT wp = NULL; 814 PetscInt pEnd, pStart; 815 816 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 817 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 818 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 819 numLabels = PetscMax(numLabels, 10); 820 numColors = 10; 821 numLColors = 10; 822 ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 823 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 824 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL);CHKERRQ(ierr); 825 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 826 for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 827 for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 828 n = 4; 829 ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg);CHKERRQ(ierr); 830 PetscCheckFalse(flg && n != dim+1,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 831 ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg);CHKERRQ(ierr); 832 PetscCheckFalse(flg && n != dim+1,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 833 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 834 if (!useLabels) numLabels = 0; 835 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 836 if (!useColors) { 837 numColors = 3; 838 for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 839 } 840 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 841 if (!useColors) { 842 numLColors = 4; 843 for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 844 } 845 ierr = PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg);CHKERRQ(ierr); 846 plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 847 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg);CHKERRQ(ierr); 848 PetscCheckFalse(flg && plotEdges && depth < dim,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 849 if (depth < dim) plotEdges = PETSC_FALSE; 850 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL);CHKERRQ(ierr); 851 852 /* filter points with labelvalue != labeldefaultvalue */ 853 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 854 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 855 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 856 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 857 if (lflg) { 858 DMLabel lbl; 859 860 ierr = DMGetLabel(dm, lname, &lbl);CHKERRQ(ierr); 861 if (lbl) { 862 PetscInt val, defval; 863 864 ierr = DMLabelGetDefaultValue(lbl, &defval);CHKERRQ(ierr); 865 ierr = PetscBTCreate(pEnd-pStart, &wp);CHKERRQ(ierr); 866 for (c = pStart; c < pEnd; c++) { 867 PetscInt *closure = NULL; 868 PetscInt closureSize; 869 870 ierr = DMLabelGetValue(lbl, c, &val);CHKERRQ(ierr); 871 if (val == defval) continue; 872 873 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 874 for (p = 0; p < closureSize*2; p += 2) { 875 ierr = PetscBTSet(wp, closure[p] - pStart);CHKERRQ(ierr); 876 } 877 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 878 } 879 } 880 } 881 882 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 883 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 884 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 885 ierr = PetscViewerASCIIPrintf(viewer, "\ 886 \\documentclass[tikz]{standalone}\n\n\ 887 \\usepackage{pgflibraryshapes}\n\ 888 \\usetikzlibrary{backgrounds}\n\ 889 \\usetikzlibrary{arrows}\n\ 890 \\begin{document}\n");CHKERRQ(ierr); 891 if (size > 1) { 892 ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 893 for (p = 0; p < size; ++p) { 894 if (p > 0 && p == size-1) { 895 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 896 } else if (p > 0) { 897 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 898 } 899 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 900 } 901 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 902 } 903 if (drawHasse) { 904 PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart)); 905 906 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%D}\n", vStart);CHKERRQ(ierr); 907 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%D}\n", vEnd-1);CHKERRQ(ierr); 908 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%D}\n", vEnd-vStart);CHKERRQ(ierr); 909 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.);CHKERRQ(ierr); 910 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%D}\n", eStart);CHKERRQ(ierr); 911 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%D}\n", eEnd-1);CHKERRQ(ierr); 912 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.);CHKERRQ(ierr); 913 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%D}\n", eEnd-eStart);CHKERRQ(ierr); 914 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%D}\n", cStart);CHKERRQ(ierr); 915 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%D}\n", cEnd-1);CHKERRQ(ierr); 916 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%D}\n", cEnd-cStart);CHKERRQ(ierr); 917 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.);CHKERRQ(ierr); 918 } 919 ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale);CHKERRQ(ierr); 920 921 /* Plot vertices */ 922 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 923 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 924 for (v = vStart; v < vEnd; ++v) { 925 PetscInt off, dof, d; 926 PetscBool isLabeled = PETSC_FALSE; 927 928 if (wp && !PetscBTLookup(wp,v - pStart)) continue; 929 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 930 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 931 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 932 PetscCheckFalse(dof > 3,PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 933 for (d = 0; d < dof; ++d) { 934 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 935 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 936 } 937 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 938 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 939 for (d = 0; d < dof; ++d) { 940 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 941 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]);CHKERRQ(ierr); 942 } 943 if (drawHasse) color = colors[0%numColors]; 944 else color = colors[rank%numColors]; 945 for (l = 0; l < numLabels; ++l) { 946 PetscInt val; 947 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 948 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 949 } 950 if (drawNumbers[0]) { 951 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 952 } else if (drawColors[0]) { 953 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 954 } else { 955 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", v, rank);CHKERRQ(ierr); 956 } 957 } 958 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 959 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 960 /* Plot edges */ 961 if (plotEdges) { 962 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 963 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 964 for (e = eStart; e < eEnd; ++e) { 965 const PetscInt *cone; 966 PetscInt coneSize, offA, offB, dof, d; 967 968 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 969 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 970 PetscCheckFalse(coneSize != 2,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 971 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 972 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 973 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 974 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 975 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 976 for (d = 0; d < dof; ++d) { 977 tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 978 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 979 } 980 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 981 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 982 for (d = 0; d < dof; ++d) { 983 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 984 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr); 985 } 986 if (drawHasse) color = colors[1%numColors]; 987 else color = colors[rank%numColors]; 988 for (l = 0; l < numLabels; ++l) { 989 PetscInt val; 990 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 991 if (val >= 0) {color = lcolors[l%numLColors]; break;} 992 } 993 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 994 } 995 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 996 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 997 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 998 } 999 /* Plot cells */ 1000 if (dim == 3 || !drawNumbers[1]) { 1001 for (e = eStart; e < eEnd; ++e) { 1002 const PetscInt *cone; 1003 1004 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 1005 color = colors[rank%numColors]; 1006 for (l = 0; l < numLabels; ++l) { 1007 PetscInt val; 1008 ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 1009 if (val >= 0) {color = lcolors[l%numLColors]; break;} 1010 } 1011 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 1012 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 1013 } 1014 } else { 1015 DMPolytopeType ct; 1016 1017 /* Drawing a 2D polygon */ 1018 for (c = cStart; c < cEnd; ++c) { 1019 if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1020 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 1021 if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || 1022 ct == DM_POLYTOPE_TRI_PRISM_TENSOR || 1023 ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 1024 const PetscInt *cone; 1025 PetscInt coneSize, e; 1026 1027 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 1028 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 1029 for (e = 0; e < coneSize; ++e) { 1030 const PetscInt *econe; 1031 1032 ierr = DMPlexGetCone(dm, cone[e], &econe);CHKERRQ(ierr); 1033 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d) -- (%D_%d);\n", colors[rank%numColors], econe[0], rank, cone[e], rank, econe[1], rank);CHKERRQ(ierr); 1034 } 1035 } else { 1036 PetscInt *closure = NULL; 1037 PetscInt closureSize, Nv = 0, v; 1038 1039 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1040 for (p = 0; p < closureSize*2; p += 2) { 1041 const PetscInt point = closure[p]; 1042 1043 if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1044 } 1045 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 1046 for (v = 0; v <= Nv; ++v) { 1047 const PetscInt vertex = closure[v%Nv]; 1048 1049 if (v > 0) { 1050 if (plotEdges) { 1051 const PetscInt *edge; 1052 PetscInt endpoints[2], ne; 1053 1054 endpoints[0] = closure[v-1]; endpoints[1] = vertex; 1055 ierr = DMPlexGetJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr); 1056 PetscCheckFalse(ne != 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %D, %D", endpoints[0], endpoints[1]); 1057 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d) -- ", edge[0], rank);CHKERRQ(ierr); 1058 ierr = DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr); 1059 } else { 1060 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr); 1061 } 1062 } 1063 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", vertex, rank);CHKERRQ(ierr); 1064 } 1065 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ";\n");CHKERRQ(ierr); 1066 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1067 } 1068 } 1069 } 1070 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1071 for (c = cStart; c < cEnd; ++c) { 1072 double ccoords[3] = {0.0, 0.0, 0.0}; 1073 PetscBool isLabeled = PETSC_FALSE; 1074 PetscInt *closure = NULL; 1075 PetscInt closureSize, dof, d, n = 0; 1076 1077 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 1078 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1079 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 1080 for (p = 0; p < closureSize*2; p += 2) { 1081 const PetscInt point = closure[p]; 1082 PetscInt off; 1083 1084 if ((point < vStart) || (point >= vEnd)) continue; 1085 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 1086 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 1087 for (d = 0; d < dof; ++d) { 1088 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1089 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1090 } 1091 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1092 if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1093 for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 1094 ++n; 1095 } 1096 for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 1097 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1098 for (d = 0; d < dof; ++d) { 1099 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 1100 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]);CHKERRQ(ierr); 1101 } 1102 if (drawHasse) color = colors[depth%numColors]; 1103 else color = colors[rank%numColors]; 1104 for (l = 0; l < numLabels; ++l) { 1105 PetscInt val; 1106 ierr = DMGetLabelValue(dm, names[l], c, &val);CHKERRQ(ierr); 1107 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 1108 } 1109 if (drawNumbers[dim]) { 1110 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c);CHKERRQ(ierr); 1111 } else if (drawColors[dim]) { 1112 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 1113 } else { 1114 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", c, rank);CHKERRQ(ierr); 1115 } 1116 } 1117 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1118 if (drawHasse) { 1119 color = colors[depth%numColors]; 1120 ierr = PetscViewerASCIIPrintf(viewer, "%% Cells\n");CHKERRQ(ierr); 1121 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n");CHKERRQ(ierr); 1122 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1123 ierr = PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color);CHKERRQ(ierr); 1124 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1125 1126 color = colors[1%numColors]; 1127 ierr = PetscViewerASCIIPrintf(viewer, "%% Edges\n");CHKERRQ(ierr); 1128 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n");CHKERRQ(ierr); 1129 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1130 ierr = PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color);CHKERRQ(ierr); 1131 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1132 1133 color = colors[0%numColors]; 1134 ierr = PetscViewerASCIIPrintf(viewer, "%% Vertices\n");CHKERRQ(ierr); 1135 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n");CHKERRQ(ierr); 1136 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1137 ierr = PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color);CHKERRQ(ierr); 1138 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1139 1140 for (p = pStart; p < pEnd; ++p) { 1141 const PetscInt *cone; 1142 PetscInt coneSize, cp; 1143 1144 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1145 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1146 for (cp = 0; cp < coneSize; ++cp) { 1147 ierr = PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%D_%d) -- (%D_%d);\n", cone[cp], rank, p, rank);CHKERRQ(ierr); 1148 } 1149 } 1150 } 1151 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1152 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 1153 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 1154 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 1155 for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 1156 for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 1157 for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 1158 ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 1159 ierr = PetscBTDestroy(&wp);CHKERRQ(ierr); 1160 } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 1161 Vec cown,acown; 1162 VecScatter sct; 1163 ISLocalToGlobalMapping g2l; 1164 IS gid,acis; 1165 MPI_Comm comm,ncomm = MPI_COMM_NULL; 1166 MPI_Group ggroup,ngroup; 1167 PetscScalar *array,nid; 1168 const PetscInt *idxs; 1169 PetscInt *idxs2,*start,*adjacency,*work; 1170 PetscInt64 lm[3],gm[3]; 1171 PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 1172 PetscMPIInt d1,d2,rank; 1173 1174 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1175 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 1176 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1177 ierr = MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm);CHKERRMPI(ierr); 1178 #endif 1179 if (ncomm != MPI_COMM_NULL) { 1180 ierr = MPI_Comm_group(comm,&ggroup);CHKERRMPI(ierr); 1181 ierr = MPI_Comm_group(ncomm,&ngroup);CHKERRMPI(ierr); 1182 d1 = 0; 1183 ierr = MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2);CHKERRMPI(ierr); 1184 nid = d2; 1185 ierr = MPI_Group_free(&ggroup);CHKERRMPI(ierr); 1186 ierr = MPI_Group_free(&ngroup);CHKERRMPI(ierr); 1187 ierr = MPI_Comm_free(&ncomm);CHKERRMPI(ierr); 1188 } else nid = 0.0; 1189 1190 /* Get connectivity */ 1191 ierr = DMPlexGetVTKCellHeight(dm,&cellHeight);CHKERRQ(ierr); 1192 ierr = DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid);CHKERRQ(ierr); 1193 1194 /* filter overlapped local cells */ 1195 ierr = DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd);CHKERRQ(ierr); 1196 ierr = ISGetIndices(gid,&idxs);CHKERRQ(ierr); 1197 ierr = ISGetLocalSize(gid,&cum);CHKERRQ(ierr); 1198 ierr = PetscMalloc1(cum,&idxs2);CHKERRQ(ierr); 1199 for (c = cStart, cum = 0; c < cEnd; c++) { 1200 if (idxs[c-cStart] < 0) continue; 1201 idxs2[cum++] = idxs[c-cStart]; 1202 } 1203 ierr = ISRestoreIndices(gid,&idxs);CHKERRQ(ierr); 1204 PetscCheckFalse(numVertices != cum,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum); 1205 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1206 ierr = ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid);CHKERRQ(ierr); 1207 1208 /* support for node-aware cell locality */ 1209 ierr = ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis);CHKERRQ(ierr); 1210 ierr = VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown);CHKERRQ(ierr); 1211 ierr = VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown);CHKERRQ(ierr); 1212 ierr = VecGetArray(cown,&array);CHKERRQ(ierr); 1213 for (c = 0; c < numVertices; c++) array[c] = nid; 1214 ierr = VecRestoreArray(cown,&array);CHKERRQ(ierr); 1215 ierr = VecScatterCreate(cown,acis,acown,NULL,&sct);CHKERRQ(ierr); 1216 ierr = VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1217 ierr = VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1218 ierr = ISDestroy(&acis);CHKERRQ(ierr); 1219 ierr = VecScatterDestroy(&sct);CHKERRQ(ierr); 1220 ierr = VecDestroy(&cown);CHKERRQ(ierr); 1221 1222 /* compute edgeCut */ 1223 for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 1224 ierr = PetscMalloc1(cum,&work);CHKERRQ(ierr); 1225 ierr = ISLocalToGlobalMappingCreateIS(gid,&g2l);CHKERRQ(ierr); 1226 ierr = ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 1227 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1228 ierr = VecGetArray(acown,&array);CHKERRQ(ierr); 1229 for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 1230 PetscInt totl; 1231 1232 totl = start[c+1]-start[c]; 1233 ierr = ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work);CHKERRQ(ierr); 1234 for (i = 0; i < totl; i++) { 1235 if (work[i] < 0) { 1236 ect += 1; 1237 ectn += (array[i + start[c]] != nid) ? 0 : 1; 1238 } 1239 } 1240 } 1241 ierr = PetscFree(work);CHKERRQ(ierr); 1242 ierr = VecRestoreArray(acown,&array);CHKERRQ(ierr); 1243 lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 1244 lm[1] = -numVertices; 1245 ierr = MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm);CHKERRMPI(ierr); 1246 ierr = PetscViewerASCIIPrintf(viewer," Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]);CHKERRQ(ierr); 1247 lm[0] = ect; /* edgeCut */ 1248 lm[1] = ectn; /* node-aware edgeCut */ 1249 lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 1250 ierr = MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr); 1251 ierr = PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]);CHKERRQ(ierr); 1252 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1253 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),gm[0] ? ((double)(gm[1]))/((double)gm[0]) : 1.);CHKERRQ(ierr); 1254 #else 1255 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0);CHKERRQ(ierr); 1256 #endif 1257 ierr = ISLocalToGlobalMappingDestroy(&g2l);CHKERRQ(ierr); 1258 ierr = PetscFree(start);CHKERRQ(ierr); 1259 ierr = PetscFree(adjacency);CHKERRQ(ierr); 1260 ierr = VecDestroy(&acown);CHKERRQ(ierr); 1261 } else { 1262 const char *name; 1263 PetscInt *sizes, *hybsizes, *ghostsizes; 1264 PetscInt locDepth, depth, cellHeight, dim, d; 1265 PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1266 PetscInt numLabels, l, maxSize = 17; 1267 DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1268 MPI_Comm comm; 1269 PetscMPIInt size, rank; 1270 1271 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1272 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1273 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1274 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1275 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 1276 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 1277 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1278 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1279 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 1280 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 1281 ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRMPI(ierr); 1282 ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr); 1283 gcNum = gcEnd - gcStart; 1284 if (size < maxSize) {ierr = PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes);CHKERRQ(ierr);} 1285 else {ierr = PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes);CHKERRQ(ierr);} 1286 for (d = 0; d <= depth; d++) { 1287 PetscInt Nc[2] = {0, 0}, ict; 1288 1289 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 1290 if (pStart < pEnd) {ierr = DMPlexGetCellType(dm, pStart, &ct0);CHKERRQ(ierr);} 1291 ict = ct0; 1292 ierr = MPI_Bcast(&ict, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1293 ct0 = (DMPolytopeType) ict; 1294 for (p = pStart; p < pEnd; ++p) { 1295 DMPolytopeType ct; 1296 1297 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 1298 if (ct == ct0) ++Nc[0]; 1299 else ++Nc[1]; 1300 } 1301 if (size < maxSize) { 1302 ierr = MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1303 ierr = MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1304 if (d == depth) {ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);} 1305 ierr = PetscViewerASCIIPrintf(viewer, " Number of %D-cells per rank:", (depth == 1) && d ? dim : d);CHKERRQ(ierr); 1306 for (p = 0; p < size; ++p) { 1307 if (rank == 0) { 1308 ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]);CHKERRQ(ierr); 1309 if (hybsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]);CHKERRQ(ierr);} 1310 if (ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);} 1311 } 1312 } 1313 } else { 1314 PetscInt locMinMax[2]; 1315 1316 locMinMax[0] = Nc[0]+Nc[1]; locMinMax[1] = Nc[0]+Nc[1]; 1317 ierr = PetscGlobalMinMaxInt(comm, locMinMax, sizes);CHKERRQ(ierr); 1318 locMinMax[0] = Nc[1]; locMinMax[1] = Nc[1]; 1319 ierr = PetscGlobalMinMaxInt(comm, locMinMax, hybsizes);CHKERRQ(ierr); 1320 if (d == depth) { 1321 locMinMax[0] = gcNum; locMinMax[1] = gcNum; 1322 ierr = PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes);CHKERRQ(ierr); 1323 } 1324 ierr = PetscViewerASCIIPrintf(viewer, " Min/Max of %D-cells per rank:", (depth == 1) && d ? dim : d);CHKERRQ(ierr); 1325 ierr = PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]);CHKERRQ(ierr); 1326 if (hybsizes[0] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]);CHKERRQ(ierr);} 1327 if (ghostsizes[0] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]);CHKERRQ(ierr);} 1328 } 1329 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 1330 } 1331 ierr = PetscFree3(sizes, hybsizes, ghostsizes);CHKERRQ(ierr); 1332 { 1333 const PetscReal *maxCell; 1334 const PetscReal *L; 1335 const DMBoundaryType *bd; 1336 PetscBool per, localized; 1337 1338 ierr = DMGetPeriodicity(dm, &per, &maxCell, &L, &bd);CHKERRQ(ierr); 1339 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 1340 if (per) { 1341 ierr = PetscViewerASCIIPrintf(viewer, "Periodic mesh (");CHKERRQ(ierr); 1342 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1343 for (d = 0; d < dim; ++d) { 1344 if (bd && d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1345 if (bd) {ierr = PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]]);CHKERRQ(ierr);} 1346 } 1347 ierr = PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized");CHKERRQ(ierr); 1348 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1349 } 1350 } 1351 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 1352 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 1353 for (l = 0; l < numLabels; ++l) { 1354 DMLabel label; 1355 const char *name; 1356 IS valueIS; 1357 const PetscInt *values; 1358 PetscInt numValues, v; 1359 1360 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 1361 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1362 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 1363 ierr = PetscViewerASCIIPrintf(viewer, " %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr); 1364 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 1365 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 1366 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1367 for (v = 0; v < numValues; ++v) { 1368 PetscInt size; 1369 1370 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 1371 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1372 ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr); 1373 } 1374 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 1375 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1376 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 1377 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 1378 } 1379 { 1380 char **labelNames; 1381 PetscInt Nl = numLabels; 1382 PetscBool flg; 1383 1384 ierr = PetscMalloc1(Nl, &labelNames);CHKERRQ(ierr); 1385 ierr = PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg);CHKERRQ(ierr); 1386 for (l = 0; l < Nl; ++l) { 1387 DMLabel label; 1388 1389 ierr = DMHasLabel(dm, labelNames[l], &flg);CHKERRQ(ierr); 1390 if (flg) { 1391 ierr = DMGetLabel(dm, labelNames[l], &label);CHKERRQ(ierr); 1392 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 1393 } 1394 ierr = PetscFree(labelNames[l]);CHKERRQ(ierr); 1395 } 1396 ierr = PetscFree(labelNames);CHKERRQ(ierr); 1397 } 1398 /* If no fields are specified, people do not want to see adjacency */ 1399 if (dm->Nf) { 1400 PetscInt f; 1401 1402 for (f = 0; f < dm->Nf; ++f) { 1403 const char *name; 1404 1405 ierr = PetscObjectGetName(dm->fields[f].disc, &name);CHKERRQ(ierr); 1406 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Field %s:\n", name);CHKERRQ(ierr);} 1407 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1408 if (dm->fields[f].label) {ierr = DMLabelView(dm->fields[f].label, viewer);CHKERRQ(ierr);} 1409 if (dm->fields[f].adjacency[0]) { 1410 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n");CHKERRQ(ierr);} 1411 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM\n");CHKERRQ(ierr);} 1412 } else { 1413 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FEM\n");CHKERRQ(ierr);} 1414 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n");CHKERRQ(ierr);} 1415 } 1416 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1417 } 1418 } 1419 ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr); 1420 if (cdm) { 1421 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1422 ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr); 1423 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1424 } 1425 } 1426 PetscFunctionReturn(0); 1427 } 1428 1429 static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1430 { 1431 DMPolytopeType ct; 1432 PetscMPIInt rank; 1433 PetscInt cdim; 1434 PetscErrorCode ierr; 1435 1436 PetscFunctionBegin; 1437 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1438 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1439 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 1440 switch (ct) { 1441 case DM_POLYTOPE_SEGMENT: 1442 case DM_POLYTOPE_POINT_PRISM_TENSOR: 1443 switch (cdim) { 1444 case 1: 1445 { 1446 const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1447 const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1448 1449 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK);CHKERRQ(ierr); 1450 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), y+dy, PetscRealPart(coords[0]), y-dy, PETSC_DRAW_BLACK);CHKERRQ(ierr); 1451 ierr = PetscDrawLine(draw, PetscRealPart(coords[1]), y+dy, PetscRealPart(coords[1]), y-dy, PETSC_DRAW_BLACK);CHKERRQ(ierr); 1452 } 1453 break; 1454 case 2: 1455 { 1456 const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1457 const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1458 const PetscReal l = 0.1/PetscSqrtReal(dx*dx + dy*dy); 1459 1460 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1461 ierr = PetscDrawLine(draw, PetscRealPart(coords[0])+l*dx, PetscRealPart(coords[1])+l*dy, PetscRealPart(coords[0])-l*dx, PetscRealPart(coords[1])-l*dy, PETSC_DRAW_BLACK);CHKERRQ(ierr); 1462 ierr = PetscDrawLine(draw, PetscRealPart(coords[2])+l*dx, PetscRealPart(coords[3])+l*dy, PetscRealPart(coords[2])-l*dx, PetscRealPart(coords[3])-l*dy, PETSC_DRAW_BLACK);CHKERRQ(ierr); 1463 } 1464 break; 1465 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %D", cdim); 1466 } 1467 break; 1468 case DM_POLYTOPE_TRIANGLE: 1469 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1470 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1471 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1472 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1473 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1474 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1475 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1476 break; 1477 case DM_POLYTOPE_QUADRILATERAL: 1478 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1479 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1480 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1481 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1482 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1483 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1484 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1485 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1486 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1487 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1488 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1489 ierr = PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1490 break; 1491 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1492 } 1493 PetscFunctionReturn(0); 1494 } 1495 1496 static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1497 { 1498 DMPolytopeType ct; 1499 PetscReal centroid[2] = {0., 0.}; 1500 PetscMPIInt rank; 1501 PetscInt fillColor, v, e, d; 1502 PetscErrorCode ierr; 1503 1504 PetscFunctionBegin; 1505 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1506 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1507 fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2; 1508 switch (ct) { 1509 case DM_POLYTOPE_TRIANGLE: 1510 { 1511 PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1512 1513 for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;} 1514 for (e = 0; e < 3; ++e) { 1515 refCoords[0] = refVertices[e*2+0]; 1516 refCoords[1] = refVertices[e*2+1]; 1517 for (d = 1; d <= edgeDiv; ++d) { 1518 refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv; 1519 refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv; 1520 } 1521 ierr = DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords);CHKERRQ(ierr); 1522 for (d = 0; d < edgeDiv; ++d) { 1523 ierr = PetscDrawTriangle(draw, centroid[0], centroid[1], edgeCoords[d*2+0], edgeCoords[d*2+1], edgeCoords[(d+1)*2+0], edgeCoords[(d+1)*2+1], fillColor, fillColor, fillColor);CHKERRQ(ierr); 1524 ierr = PetscDrawLine(draw, edgeCoords[d*2+0], edgeCoords[d*2+1], edgeCoords[(d+1)*2+0], edgeCoords[(d+1)*2+1], PETSC_DRAW_BLACK);CHKERRQ(ierr); 1525 } 1526 } 1527 } 1528 break; 1529 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1530 } 1531 PetscFunctionReturn(0); 1532 } 1533 1534 static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1535 { 1536 PetscDraw draw; 1537 DM cdm; 1538 PetscSection coordSection; 1539 Vec coordinates; 1540 const PetscScalar *coords; 1541 PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1542 PetscReal *refCoords, *edgeCoords; 1543 PetscBool isnull, drawAffine = PETSC_TRUE; 1544 PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1545 PetscErrorCode ierr; 1546 1547 PetscFunctionBegin; 1548 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 1549 PetscCheckFalse(dim > 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim); 1550 ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL);CHKERRQ(ierr); 1551 if (!drawAffine) {ierr = PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords);CHKERRQ(ierr);} 1552 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 1553 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1554 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 1555 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1556 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1557 1558 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 1559 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 1560 if (isnull) PetscFunctionReturn(0); 1561 ierr = PetscDrawSetTitle(draw, "Mesh");CHKERRQ(ierr); 1562 1563 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 1564 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 1565 for (c = 0; c < N; c += dim) { 1566 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 1567 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1568 } 1569 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 1570 ierr = MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1571 ierr = MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1572 ierr = PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]);CHKERRQ(ierr); 1573 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 1574 1575 for (c = cStart; c < cEnd; ++c) { 1576 PetscScalar *coords = NULL; 1577 PetscInt numCoords; 1578 1579 ierr = DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords);CHKERRQ(ierr); 1580 if (drawAffine) { 1581 ierr = DMPlexDrawCell(dm, draw, c, coords);CHKERRQ(ierr); 1582 } else { 1583 ierr = DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords);CHKERRQ(ierr); 1584 } 1585 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 1586 } 1587 if (!drawAffine) {ierr = PetscFree2(refCoords, edgeCoords);CHKERRQ(ierr);} 1588 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1589 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 1590 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 1591 PetscFunctionReturn(0); 1592 } 1593 1594 #if defined(PETSC_HAVE_EXODUSII) 1595 #include <exodusII.h> 1596 #include <petscviewerexodusii.h> 1597 #endif 1598 1599 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1600 { 1601 PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1602 char name[PETSC_MAX_PATH_LEN]; 1603 PetscErrorCode ierr; 1604 1605 PetscFunctionBegin; 1606 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1607 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1608 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1609 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1610 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1611 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 1612 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 1613 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus);CHKERRQ(ierr); 1614 if (iascii) { 1615 PetscViewerFormat format; 1616 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1617 if (format == PETSC_VIEWER_ASCII_GLVIS) { 1618 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1619 } else { 1620 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 1621 } 1622 } else if (ishdf5) { 1623 #if defined(PETSC_HAVE_HDF5) 1624 ierr = DMPlexView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1625 #else 1626 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1627 #endif 1628 } else if (isvtk) { 1629 ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr); 1630 } else if (isdraw) { 1631 ierr = DMPlexView_Draw(dm, viewer);CHKERRQ(ierr); 1632 } else if (isglvis) { 1633 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1634 #if defined(PETSC_HAVE_EXODUSII) 1635 } else if (isexodus) { 1636 /* 1637 exodusII requires that all sets be part of exactly one cell set. 1638 If the dm does not have a "Cell Sets" label defined, we create one 1639 with ID 1, containig all cells. 1640 Note that if the Cell Sets label is defined but does not cover all cells, 1641 we may still have a problem. This should probably be checked here or in the viewer; 1642 */ 1643 PetscInt numCS; 1644 ierr = DMGetLabelSize(dm,"Cell Sets",&numCS);CHKERRQ(ierr); 1645 if (!numCS) { 1646 PetscInt cStart, cEnd, c; 1647 ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr); 1648 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1649 for (c = cStart; c < cEnd; ++c) {ierr = DMSetLabelValue(dm, "Cell Sets", c, 1);CHKERRQ(ierr);} 1650 } 1651 ierr = DMView_PlexExodusII(dm, viewer);CHKERRQ(ierr); 1652 #endif 1653 } else { 1654 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1655 } 1656 /* Optionally view the partition */ 1657 ierr = PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg);CHKERRQ(ierr); 1658 if (flg) { 1659 Vec ranks; 1660 ierr = DMPlexCreateRankField(dm, &ranks);CHKERRQ(ierr); 1661 ierr = VecView(ranks, viewer);CHKERRQ(ierr); 1662 ierr = VecDestroy(&ranks);CHKERRQ(ierr); 1663 } 1664 /* Optionally view a label */ 1665 ierr = PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg);CHKERRQ(ierr); 1666 if (flg) { 1667 DMLabel label; 1668 Vec val; 1669 1670 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1671 PetscCheckFalse(!label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 1672 ierr = DMPlexCreateLabelField(dm, label, &val);CHKERRQ(ierr); 1673 ierr = VecView(val, viewer);CHKERRQ(ierr); 1674 ierr = VecDestroy(&val);CHKERRQ(ierr); 1675 } 1676 PetscFunctionReturn(0); 1677 } 1678 1679 /*@ 1680 DMPlexTopologyView - Saves a DMPlex topology into a file 1681 1682 Collective on DM 1683 1684 Input Parameters: 1685 + dm - The DM whose topology is to be saved 1686 - viewer - The PetscViewer for saving 1687 1688 Level: advanced 1689 1690 .seealso: DMView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexTopologyLoad() 1691 @*/ 1692 PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 1693 { 1694 PetscBool ishdf5; 1695 PetscErrorCode ierr; 1696 1697 PetscFunctionBegin; 1698 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1699 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1700 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1701 ierr = PetscLogEventBegin(DMPLEX_TopologyView,viewer,0,0,0);CHKERRQ(ierr); 1702 if (ishdf5) { 1703 #if defined(PETSC_HAVE_HDF5) 1704 PetscViewerFormat format; 1705 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1706 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1707 IS globalPointNumbering; 1708 1709 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1710 ierr = DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1711 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1712 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 1713 #else 1714 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1715 #endif 1716 } 1717 ierr = PetscLogEventEnd(DMPLEX_TopologyView,viewer,0,0,0);CHKERRQ(ierr); 1718 PetscFunctionReturn(0); 1719 } 1720 1721 /*@ 1722 DMPlexCoordinatesView - Saves DMPlex coordinates into a file 1723 1724 Collective on DM 1725 1726 Input Parameters: 1727 + dm - The DM whose coordinates are to be saved 1728 - viewer - The PetscViewer for saving 1729 1730 Level: advanced 1731 1732 .seealso: DMView(), DMPlexTopologyView(), DMPlexLabelsView(), DMPlexCoordinatesLoad() 1733 @*/ 1734 PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 1735 { 1736 PetscBool ishdf5; 1737 PetscErrorCode ierr; 1738 1739 PetscFunctionBegin; 1740 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1741 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1742 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1743 ierr = PetscLogEventBegin(DMPLEX_CoordinatesView,viewer,0,0,0);CHKERRQ(ierr); 1744 if (ishdf5) { 1745 #if defined(PETSC_HAVE_HDF5) 1746 PetscViewerFormat format; 1747 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1748 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1749 ierr = DMPlexCoordinatesView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1750 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1751 #else 1752 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1753 #endif 1754 } 1755 ierr = PetscLogEventEnd(DMPLEX_CoordinatesView,viewer,0,0,0);CHKERRQ(ierr); 1756 PetscFunctionReturn(0); 1757 } 1758 1759 /*@ 1760 DMPlexLabelsView - Saves DMPlex labels into a file 1761 1762 Collective on DM 1763 1764 Input Parameters: 1765 + dm - The DM whose labels are to be saved 1766 - viewer - The PetscViewer for saving 1767 1768 Level: advanced 1769 1770 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsLoad() 1771 @*/ 1772 PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1773 { 1774 PetscBool ishdf5; 1775 PetscErrorCode ierr; 1776 1777 PetscFunctionBegin; 1778 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1779 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1780 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1781 ierr = PetscLogEventBegin(DMPLEX_LabelsView,viewer,0,0,0);CHKERRQ(ierr); 1782 if (ishdf5) { 1783 #if defined(PETSC_HAVE_HDF5) 1784 IS globalPointNumbering; 1785 PetscViewerFormat format; 1786 1787 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1788 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1789 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1790 ierr = DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1791 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1792 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1793 #else 1794 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1795 #endif 1796 } 1797 ierr = PetscLogEventEnd(DMPLEX_LabelsView,viewer,0,0,0);CHKERRQ(ierr); 1798 PetscFunctionReturn(0); 1799 } 1800 1801 /*@ 1802 DMPlexSectionView - Saves a section associated with a DMPlex 1803 1804 Collective on DM 1805 1806 Input Parameters: 1807 + dm - The DM that contains the topology on which the section to be saved is defined 1808 . viewer - The PetscViewer for saving 1809 - sectiondm - The DM that contains the section to be saved 1810 1811 Level: advanced 1812 1813 Notes: 1814 This function is a wrapper around PetscSectionView(); in addition to the raw section, it saves information that associates the section points to the topology (dm) points. When the topology (dm) and the section are later loaded with DMPlexTopologyLoad() and DMPlexSectionLoad(), respectively, this information is used to match section points with topology points. 1815 1816 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 1817 1818 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexGlobalVectorView(), DMPlexLocalVectorView(), PetscSectionView(), DMPlexSectionLoad() 1819 @*/ 1820 PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1821 { 1822 PetscBool ishdf5; 1823 PetscErrorCode ierr; 1824 1825 PetscFunctionBegin; 1826 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1827 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1828 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1829 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 1830 ierr = PetscLogEventBegin(DMPLEX_SectionView,viewer,0,0,0);CHKERRQ(ierr); 1831 if (ishdf5) { 1832 #if defined(PETSC_HAVE_HDF5) 1833 ierr = DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm);CHKERRQ(ierr); 1834 #else 1835 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1836 #endif 1837 } 1838 ierr = PetscLogEventEnd(DMPLEX_SectionView,viewer,0,0,0);CHKERRQ(ierr); 1839 PetscFunctionReturn(0); 1840 } 1841 1842 /*@ 1843 DMPlexGlobalVectorView - Saves a global vector 1844 1845 Collective on DM 1846 1847 Input Parameters: 1848 + dm - The DM that represents the topology 1849 . viewer - The PetscViewer to save data with 1850 . sectiondm - The DM that contains the global section on which vec is defined 1851 - vec - The global vector to be saved 1852 1853 Level: advanced 1854 1855 Notes: 1856 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 1857 1858 Typical calling sequence 1859 $ DMCreate(PETSC_COMM_WORLD, &dm); 1860 $ DMSetType(dm, DMPLEX); 1861 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1862 $ DMClone(dm, §iondm); 1863 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1864 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1865 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1866 $ PetscSectionSetChart(section, pStart, pEnd); 1867 $ PetscSectionSetUp(section); 1868 $ DMSetLocalSection(sectiondm, section); 1869 $ PetscSectionDestroy(§ion); 1870 $ DMGetGlobalVector(sectiondm, &vec); 1871 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1872 $ DMPlexTopologyView(dm, viewer); 1873 $ DMPlexSectionView(dm, viewer, sectiondm); 1874 $ DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 1875 $ DMRestoreGlobalVector(sectiondm, &vec); 1876 $ DMDestroy(§iondm); 1877 $ DMDestroy(&dm); 1878 1879 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexLocalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1880 @*/ 1881 PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1882 { 1883 PetscBool ishdf5; 1884 PetscErrorCode ierr; 1885 1886 PetscFunctionBegin; 1887 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1888 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1889 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1890 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1891 /* Check consistency */ 1892 { 1893 PetscSection section; 1894 PetscBool includesConstraints; 1895 PetscInt m, m1; 1896 1897 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1898 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 1899 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1900 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1901 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1902 PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 1903 } 1904 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1905 ierr = PetscLogEventBegin(DMPLEX_GlobalVectorView,viewer,0,0,0);CHKERRQ(ierr); 1906 if (ishdf5) { 1907 #if defined(PETSC_HAVE_HDF5) 1908 ierr = DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1909 #else 1910 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1911 #endif 1912 } 1913 ierr = PetscLogEventEnd(DMPLEX_GlobalVectorView,viewer,0,0,0);CHKERRQ(ierr); 1914 PetscFunctionReturn(0); 1915 } 1916 1917 /*@ 1918 DMPlexLocalVectorView - Saves a local vector 1919 1920 Collective on DM 1921 1922 Input Parameters: 1923 + dm - The DM that represents the topology 1924 . viewer - The PetscViewer to save data with 1925 . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm 1926 - vec - The local vector to be saved 1927 1928 Level: advanced 1929 1930 Notes: 1931 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 1932 1933 Typical calling sequence 1934 $ DMCreate(PETSC_COMM_WORLD, &dm); 1935 $ DMSetType(dm, DMPLEX); 1936 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1937 $ DMClone(dm, §iondm); 1938 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1939 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1940 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1941 $ PetscSectionSetChart(section, pStart, pEnd); 1942 $ PetscSectionSetUp(section); 1943 $ DMSetLocalSection(sectiondm, section); 1944 $ DMGetLocalVector(sectiondm, &vec); 1945 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1946 $ DMPlexTopologyView(dm, viewer); 1947 $ DMPlexSectionView(dm, viewer, sectiondm); 1948 $ DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 1949 $ DMRestoreLocalVector(sectiondm, &vec); 1950 $ DMDestroy(§iondm); 1951 $ DMDestroy(&dm); 1952 1953 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexGlobalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1954 @*/ 1955 PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1956 { 1957 PetscBool ishdf5; 1958 PetscErrorCode ierr; 1959 1960 PetscFunctionBegin; 1961 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1962 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1963 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1964 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1965 /* Check consistency */ 1966 { 1967 PetscSection section; 1968 PetscBool includesConstraints; 1969 PetscInt m, m1; 1970 1971 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1972 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 1973 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1974 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1975 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1976 PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 1977 } 1978 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1979 ierr = PetscLogEventBegin(DMPLEX_LocalVectorView,viewer,0,0,0);CHKERRQ(ierr); 1980 if (ishdf5) { 1981 #if defined(PETSC_HAVE_HDF5) 1982 ierr = DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1983 #else 1984 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1985 #endif 1986 } 1987 ierr = PetscLogEventEnd(DMPLEX_LocalVectorView,viewer,0,0,0);CHKERRQ(ierr); 1988 PetscFunctionReturn(0); 1989 } 1990 1991 PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 1992 { 1993 PetscBool ishdf5; 1994 PetscErrorCode ierr; 1995 1996 PetscFunctionBegin; 1997 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1998 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1999 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2000 if (ishdf5) { 2001 #if defined(PETSC_HAVE_HDF5) 2002 PetscViewerFormat format; 2003 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2004 if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 2005 ierr = DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer);CHKERRQ(ierr); 2006 } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2007 ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 2008 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2009 PetscFunctionReturn(0); 2010 #else 2011 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2012 #endif 2013 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2014 } 2015 2016 /*@ 2017 DMPlexTopologyLoad - Loads a topology into a DMPlex 2018 2019 Collective on DM 2020 2021 Input Parameters: 2022 + dm - The DM into which the topology is loaded 2023 - viewer - The PetscViewer for the saved topology 2024 2025 Output Parameters: 2026 . globalToLocalPointSF - The PetscSF that pushes points in [0, N) to the associated points in the loaded plex, where N is the global number of points; NULL if unneeded 2027 2028 Level: advanced 2029 2030 .seealso: DMLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2031 @*/ 2032 PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2033 { 2034 PetscBool ishdf5; 2035 PetscErrorCode ierr; 2036 2037 PetscFunctionBegin; 2038 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2039 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2040 if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 2041 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2042 ierr = PetscLogEventBegin(DMPLEX_TopologyLoad,viewer,0,0,0);CHKERRQ(ierr); 2043 if (ishdf5) { 2044 #if defined(PETSC_HAVE_HDF5) 2045 PetscViewerFormat format; 2046 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2047 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2048 ierr = DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 2049 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2050 #else 2051 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2052 #endif 2053 } 2054 ierr = PetscLogEventEnd(DMPLEX_TopologyLoad,viewer,0,0,0);CHKERRQ(ierr); 2055 PetscFunctionReturn(0); 2056 } 2057 2058 /*@ 2059 DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 2060 2061 Collective on DM 2062 2063 Input Parameters: 2064 + dm - The DM into which the coordinates are loaded 2065 . viewer - The PetscViewer for the saved coordinates 2066 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2067 2068 Level: advanced 2069 2070 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2071 @*/ 2072 PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2073 { 2074 PetscBool ishdf5; 2075 PetscErrorCode ierr; 2076 2077 PetscFunctionBegin; 2078 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2079 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2080 PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 2081 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2082 ierr = PetscLogEventBegin(DMPLEX_CoordinatesLoad,viewer,0,0,0);CHKERRQ(ierr); 2083 if (ishdf5) { 2084 #if defined(PETSC_HAVE_HDF5) 2085 PetscViewerFormat format; 2086 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2087 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2088 ierr = DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 2089 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2090 #else 2091 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2092 #endif 2093 } 2094 ierr = PetscLogEventEnd(DMPLEX_CoordinatesLoad,viewer,0,0,0);CHKERRQ(ierr); 2095 PetscFunctionReturn(0); 2096 } 2097 2098 /*@ 2099 DMPlexLabelsLoad - Loads labels into a DMPlex 2100 2101 Collective on DM 2102 2103 Input Parameters: 2104 + dm - The DM into which the labels are loaded 2105 . viewer - The PetscViewer for the saved labels 2106 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2107 2108 Level: advanced 2109 2110 Notes: 2111 The PetscSF argument must not be NULL if the DM is distributed, otherwise an error occurs. 2112 2113 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2114 @*/ 2115 PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2116 { 2117 PetscBool ishdf5; 2118 PetscErrorCode ierr; 2119 2120 PetscFunctionBegin; 2121 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2122 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2123 if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 2124 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2125 ierr = PetscLogEventBegin(DMPLEX_LabelsLoad,viewer,0,0,0);CHKERRQ(ierr); 2126 if (ishdf5) { 2127 #if defined(PETSC_HAVE_HDF5) 2128 PetscViewerFormat format; 2129 2130 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2131 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2132 ierr = DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 2133 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2134 #else 2135 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2136 #endif 2137 } 2138 ierr = PetscLogEventEnd(DMPLEX_LabelsLoad,viewer,0,0,0);CHKERRQ(ierr); 2139 PetscFunctionReturn(0); 2140 } 2141 2142 /*@ 2143 DMPlexSectionLoad - Loads section into a DMPlex 2144 2145 Collective on DM 2146 2147 Input Parameters: 2148 + dm - The DM that represents the topology 2149 . viewer - The PetscViewer that represents the on-disk section (sectionA) 2150 . sectiondm - The DM into which the on-disk section (sectionA) is migrated 2151 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2152 2153 Output Parameters 2154 + globalDofSF - The SF that migrates any on-disk Vec data associated with sectionA into a global Vec associated with the sectiondm's global section (NULL if not needed) 2155 - localDofSF - The SF that migrates any on-disk Vec data associated with sectionA into a local Vec associated with the sectiondm's local section (NULL if not needed) 2156 2157 Level: advanced 2158 2159 Notes: 2160 This function is a wrapper around PetscSectionLoad(); it loads, in addition to the raw section, a list of global point numbers that associates each on-disk section point with a global point number in [0, NX), where NX is the number of topology points in dm. Noting that globalToLocalPointSF associates each topology point in dm with a global number in [0, NX), one can readily establish an association of the on-disk section points with the topology points. 2161 2162 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2163 2164 The output parameter, globalDofSF (localDofSF), can later be used with DMPlexGlobalVectorLoad() (DMPlexLocalVectorLoad()) to load on-disk vectors into global (local) vectors associated with sectiondm's global (local) section. 2165 2166 Example using 2 processes: 2167 $ NX (number of points on dm): 4 2168 $ sectionA : the on-disk section 2169 $ vecA : a vector associated with sectionA 2170 $ sectionB : sectiondm's local section constructed in this function 2171 $ vecB (local) : a vector associated with sectiondm's local section 2172 $ vecB (global) : a vector associated with sectiondm's global section 2173 $ 2174 $ rank 0 rank 1 2175 $ vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2176 $ sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2177 $ sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2178 $ sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2179 $ [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2180 $ sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2181 $ sectionB->atlasDof : 1 0 1 | 1 3 2182 $ sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2183 $ vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2184 $ vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2185 $ 2186 $ where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2187 2188 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad(), PetscSectionLoad(), DMPlexSectionView() 2189 @*/ 2190 PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2191 { 2192 PetscBool ishdf5; 2193 PetscErrorCode ierr; 2194 2195 PetscFunctionBegin; 2196 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2197 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2198 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2199 PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 2200 if (globalDofSF) PetscValidPointer(globalDofSF, 5); 2201 if (localDofSF) PetscValidPointer(localDofSF, 6); 2202 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2203 ierr = PetscLogEventBegin(DMPLEX_SectionLoad,viewer,0,0,0);CHKERRQ(ierr); 2204 if (ishdf5) { 2205 #if defined(PETSC_HAVE_HDF5) 2206 ierr = DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF);CHKERRQ(ierr); 2207 #else 2208 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2209 #endif 2210 } 2211 ierr = PetscLogEventEnd(DMPLEX_SectionLoad,viewer,0,0,0);CHKERRQ(ierr); 2212 PetscFunctionReturn(0); 2213 } 2214 2215 /*@ 2216 DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 2217 2218 Collective on DM 2219 2220 Input Parameters: 2221 + dm - The DM that represents the topology 2222 . viewer - The PetscViewer that represents the on-disk vector data 2223 . sectiondm - The DM that contains the global section on which vec is defined 2224 . sf - The SF that migrates the on-disk vector data into vec 2225 - vec - The global vector to set values of 2226 2227 Level: advanced 2228 2229 Notes: 2230 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2231 2232 Typical calling sequence 2233 $ DMCreate(PETSC_COMM_WORLD, &dm); 2234 $ DMSetType(dm, DMPLEX); 2235 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2236 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2237 $ DMClone(dm, §iondm); 2238 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2239 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2240 $ DMGetGlobalVector(sectiondm, &vec); 2241 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2242 $ DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2243 $ DMRestoreGlobalVector(sectiondm, &vec); 2244 $ PetscSFDestroy(&gsf); 2245 $ PetscSFDestroy(&sfX); 2246 $ DMDestroy(§iondm); 2247 $ DMDestroy(&dm); 2248 2249 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexLocalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2250 @*/ 2251 PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2252 { 2253 PetscBool ishdf5; 2254 PetscErrorCode ierr; 2255 2256 PetscFunctionBegin; 2257 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2258 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2259 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2260 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2261 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2262 /* Check consistency */ 2263 { 2264 PetscSection section; 2265 PetscBool includesConstraints; 2266 PetscInt m, m1; 2267 2268 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2269 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 2270 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2271 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2272 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2273 PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 2274 } 2275 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2276 ierr = PetscLogEventBegin(DMPLEX_GlobalVectorLoad,viewer,0,0,0);CHKERRQ(ierr); 2277 if (ishdf5) { 2278 #if defined(PETSC_HAVE_HDF5) 2279 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2280 #else 2281 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2282 #endif 2283 } 2284 ierr = PetscLogEventEnd(DMPLEX_GlobalVectorLoad,viewer,0,0,0);CHKERRQ(ierr); 2285 PetscFunctionReturn(0); 2286 } 2287 2288 /*@ 2289 DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 2290 2291 Collective on DM 2292 2293 Input Parameters: 2294 + dm - The DM that represents the topology 2295 . viewer - The PetscViewer that represents the on-disk vector data 2296 . sectiondm - The DM that contains the local section on which vec is defined 2297 . sf - The SF that migrates the on-disk vector data into vec 2298 - vec - The local vector to set values of 2299 2300 Level: advanced 2301 2302 Notes: 2303 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2304 2305 Typical calling sequence 2306 $ DMCreate(PETSC_COMM_WORLD, &dm); 2307 $ DMSetType(dm, DMPLEX); 2308 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2309 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2310 $ DMClone(dm, §iondm); 2311 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2312 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2313 $ DMGetLocalVector(sectiondm, &vec); 2314 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2315 $ DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2316 $ DMRestoreLocalVector(sectiondm, &vec); 2317 $ PetscSFDestroy(&lsf); 2318 $ PetscSFDestroy(&sfX); 2319 $ DMDestroy(§iondm); 2320 $ DMDestroy(&dm); 2321 2322 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexGlobalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2323 @*/ 2324 PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2325 { 2326 PetscBool ishdf5; 2327 PetscErrorCode ierr; 2328 2329 PetscFunctionBegin; 2330 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2331 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2332 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2333 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2334 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2335 /* Check consistency */ 2336 { 2337 PetscSection section; 2338 PetscBool includesConstraints; 2339 PetscInt m, m1; 2340 2341 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2342 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 2343 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2344 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2345 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2346 PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 2347 } 2348 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2349 ierr = PetscLogEventBegin(DMPLEX_LocalVectorLoad,viewer,0,0,0);CHKERRQ(ierr); 2350 if (ishdf5) { 2351 #if defined(PETSC_HAVE_HDF5) 2352 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2353 #else 2354 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2355 #endif 2356 } 2357 ierr = PetscLogEventEnd(DMPLEX_LocalVectorLoad,viewer,0,0,0);CHKERRQ(ierr); 2358 PetscFunctionReturn(0); 2359 } 2360 2361 PetscErrorCode DMDestroy_Plex(DM dm) 2362 { 2363 DM_Plex *mesh = (DM_Plex*) dm->data; 2364 PetscErrorCode ierr; 2365 2366 PetscFunctionBegin; 2367 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr); 2368 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr); 2369 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL);CHKERRQ(ierr); 2370 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL);CHKERRQ(ierr); 2371 if (--mesh->refct > 0) PetscFunctionReturn(0); 2372 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 2373 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 2374 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 2375 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 2376 ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr); 2377 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 2378 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 2379 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 2380 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 2381 ierr = PetscFree(mesh->transformType);CHKERRQ(ierr); 2382 ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 2383 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 2384 ierr = ISDestroy(&mesh->subpointIS);CHKERRQ(ierr); 2385 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 2386 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 2387 ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 2388 ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 2389 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 2390 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 2391 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 2392 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 2393 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 2394 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 2395 ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr); 2396 ierr = PetscFree(mesh->neighbors);CHKERRQ(ierr); 2397 if (mesh->metricCtx) { ierr = PetscFree(mesh->metricCtx);CHKERRQ(ierr); } 2398 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 2399 ierr = PetscFree(mesh);CHKERRQ(ierr); 2400 PetscFunctionReturn(0); 2401 } 2402 2403 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2404 { 2405 PetscSection sectionGlobal; 2406 PetscInt bs = -1, mbs; 2407 PetscInt localSize; 2408 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2409 PetscErrorCode ierr; 2410 MatType mtype; 2411 ISLocalToGlobalMapping ltog; 2412 2413 PetscFunctionBegin; 2414 ierr = MatInitializePackage();CHKERRQ(ierr); 2415 mtype = dm->mattype; 2416 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 2417 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 2418 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 2419 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 2420 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 2421 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 2422 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 2423 ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr); 2424 if (mbs > 1) bs = mbs; 2425 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 2426 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 2427 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 2428 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 2429 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 2430 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 2431 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 2432 ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr); 2433 if (!isShell) { 2434 PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 2435 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2]; 2436 PetscInt pStart, pEnd, p, dof, cdof; 2437 2438 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 2439 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 2440 for (p = pStart; p < pEnd; ++p) { 2441 PetscInt bdof; 2442 2443 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 2444 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 2445 dof = dof < 0 ? -(dof+1) : dof; 2446 bdof = cdof && (dof-cdof) ? 1 : dof; 2447 if (dof) { 2448 if (bs < 0) {bs = bdof;} 2449 else if (bs != bdof) {bs = 1; break;} 2450 } 2451 } 2452 /* Must have same blocksize on all procs (some might have no points) */ 2453 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2454 bsLocal[1] = bs; 2455 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 2456 if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2457 else bs = bsMinMax[0]; 2458 bs = PetscMax(1,bs); 2459 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 2460 if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 2461 ierr = MatSetBlockSize(*J, bs);CHKERRQ(ierr); 2462 ierr = MatSetUp(*J);CHKERRQ(ierr); 2463 } else { 2464 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 2465 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 2466 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 2467 } 2468 } 2469 ierr = MatSetDM(*J, dm);CHKERRQ(ierr); 2470 PetscFunctionReturn(0); 2471 } 2472 2473 /*@ 2474 DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2475 2476 Not collective 2477 2478 Input Parameter: 2479 . mesh - The DMPlex 2480 2481 Output Parameters: 2482 . subsection - The subdomain section 2483 2484 Level: developer 2485 2486 .seealso: 2487 @*/ 2488 PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2489 { 2490 DM_Plex *mesh = (DM_Plex*) dm->data; 2491 PetscErrorCode ierr; 2492 2493 PetscFunctionBegin; 2494 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2495 if (!mesh->subdomainSection) { 2496 PetscSection section; 2497 PetscSF sf; 2498 2499 ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr); 2500 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 2501 ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr); 2502 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 2503 } 2504 *subsection = mesh->subdomainSection; 2505 PetscFunctionReturn(0); 2506 } 2507 2508 /*@ 2509 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2510 2511 Not collective 2512 2513 Input Parameter: 2514 . mesh - The DMPlex 2515 2516 Output Parameters: 2517 + pStart - The first mesh point 2518 - pEnd - The upper bound for mesh points 2519 2520 Level: beginner 2521 2522 .seealso: DMPlexCreate(), DMPlexSetChart() 2523 @*/ 2524 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2525 { 2526 DM_Plex *mesh = (DM_Plex*) dm->data; 2527 PetscErrorCode ierr; 2528 2529 PetscFunctionBegin; 2530 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2531 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2532 PetscFunctionReturn(0); 2533 } 2534 2535 /*@ 2536 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2537 2538 Not collective 2539 2540 Input Parameters: 2541 + mesh - The DMPlex 2542 . pStart - The first mesh point 2543 - pEnd - The upper bound for mesh points 2544 2545 Output Parameters: 2546 2547 Level: beginner 2548 2549 .seealso: DMPlexCreate(), DMPlexGetChart() 2550 @*/ 2551 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2552 { 2553 DM_Plex *mesh = (DM_Plex*) dm->data; 2554 PetscErrorCode ierr; 2555 2556 PetscFunctionBegin; 2557 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2558 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2559 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 2560 PetscFunctionReturn(0); 2561 } 2562 2563 /*@ 2564 DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2565 2566 Not collective 2567 2568 Input Parameters: 2569 + mesh - The DMPlex 2570 - p - The point, which must lie in the chart set with DMPlexSetChart() 2571 2572 Output Parameter: 2573 . size - The cone size for point p 2574 2575 Level: beginner 2576 2577 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2578 @*/ 2579 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2580 { 2581 DM_Plex *mesh = (DM_Plex*) dm->data; 2582 PetscErrorCode ierr; 2583 2584 PetscFunctionBegin; 2585 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2586 PetscValidPointer(size, 3); 2587 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2588 PetscFunctionReturn(0); 2589 } 2590 2591 /*@ 2592 DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2593 2594 Not collective 2595 2596 Input Parameters: 2597 + mesh - The DMPlex 2598 . p - The point, which must lie in the chart set with DMPlexSetChart() 2599 - size - The cone size for point p 2600 2601 Output Parameter: 2602 2603 Note: 2604 This should be called after DMPlexSetChart(). 2605 2606 Level: beginner 2607 2608 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 2609 @*/ 2610 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2611 { 2612 DM_Plex *mesh = (DM_Plex*) dm->data; 2613 PetscErrorCode ierr; 2614 2615 PetscFunctionBegin; 2616 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2617 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2618 2619 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 2620 PetscFunctionReturn(0); 2621 } 2622 2623 /*@ 2624 DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2625 2626 Not collective 2627 2628 Input Parameters: 2629 + mesh - The DMPlex 2630 . p - The point, which must lie in the chart set with DMPlexSetChart() 2631 - size - The additional cone size for point p 2632 2633 Output Parameter: 2634 2635 Note: 2636 This should be called after DMPlexSetChart(). 2637 2638 Level: beginner 2639 2640 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 2641 @*/ 2642 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2643 { 2644 DM_Plex *mesh = (DM_Plex*) dm->data; 2645 PetscInt csize; 2646 PetscErrorCode ierr; 2647 2648 PetscFunctionBegin; 2649 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2650 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2651 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 2652 2653 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 2654 PetscFunctionReturn(0); 2655 } 2656 2657 /*@C 2658 DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2659 2660 Not collective 2661 2662 Input Parameters: 2663 + dm - The DMPlex 2664 - p - The point, which must lie in the chart set with DMPlexSetChart() 2665 2666 Output Parameter: 2667 . cone - An array of points which are on the in-edges for point p 2668 2669 Level: beginner 2670 2671 Fortran Notes: 2672 Since it returns an array, this routine is only available in Fortran 90, and you must 2673 include petsc.h90 in your code. 2674 You must also call DMPlexRestoreCone() after you finish using the returned array. 2675 DMPlexRestoreCone() is not needed/available in C. 2676 2677 .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart() 2678 @*/ 2679 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2680 { 2681 DM_Plex *mesh = (DM_Plex*) dm->data; 2682 PetscInt off; 2683 PetscErrorCode ierr; 2684 2685 PetscFunctionBegin; 2686 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2687 PetscValidPointer(cone, 3); 2688 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2689 *cone = &mesh->cones[off]; 2690 PetscFunctionReturn(0); 2691 } 2692 2693 /*@C 2694 DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 2695 2696 Not collective 2697 2698 Input Parameters: 2699 + dm - The DMPlex 2700 - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 2701 2702 Output Parameters: 2703 + pConesSection - PetscSection describing the layout of pCones 2704 - pCones - An array of points which are on the in-edges for the point set p 2705 2706 Level: intermediate 2707 2708 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart() 2709 @*/ 2710 PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 2711 { 2712 PetscSection cs, newcs; 2713 PetscInt *cones; 2714 PetscInt *newarr=NULL; 2715 PetscInt n; 2716 PetscErrorCode ierr; 2717 2718 PetscFunctionBegin; 2719 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 2720 ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr); 2721 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 2722 if (pConesSection) *pConesSection = newcs; 2723 if (pCones) { 2724 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 2725 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr); 2726 } 2727 PetscFunctionReturn(0); 2728 } 2729 2730 /*@ 2731 DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2732 2733 Not collective 2734 2735 Input Parameters: 2736 + dm - The DMPlex 2737 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2738 2739 Output Parameter: 2740 . expandedPoints - An array of vertices recursively expanded from input points 2741 2742 Level: advanced 2743 2744 Notes: 2745 Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2746 There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2747 2748 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth() 2749 @*/ 2750 PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2751 { 2752 IS *expandedPointsAll; 2753 PetscInt depth; 2754 PetscErrorCode ierr; 2755 2756 PetscFunctionBegin; 2757 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2758 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2759 PetscValidPointer(expandedPoints, 3); 2760 ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2761 *expandedPoints = expandedPointsAll[0]; 2762 ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]);CHKERRQ(ierr); 2763 ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2764 PetscFunctionReturn(0); 2765 } 2766 2767 /*@ 2768 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). 2769 2770 Not collective 2771 2772 Input Parameters: 2773 + dm - The DMPlex 2774 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2775 2776 Output Parameters: 2777 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2778 . expandedPoints - (optional) An array of index sets with recursively expanded cones 2779 - sections - (optional) An array of sections which describe mappings from points to their cone points 2780 2781 Level: advanced 2782 2783 Notes: 2784 Like DMPlexGetConeTuple() but recursive. 2785 2786 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. 2787 For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2788 2789 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: 2790 (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2791 (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2792 2793 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2794 @*/ 2795 PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2796 { 2797 const PetscInt *arr0=NULL, *cone=NULL; 2798 PetscInt *arr=NULL, *newarr=NULL; 2799 PetscInt d, depth_, i, n, newn, cn, co, start, end; 2800 IS *expandedPoints_; 2801 PetscSection *sections_; 2802 PetscErrorCode ierr; 2803 2804 PetscFunctionBegin; 2805 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2806 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2807 if (depth) PetscValidIntPointer(depth, 3); 2808 if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2809 if (sections) PetscValidPointer(sections, 5); 2810 ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr); 2811 ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr); 2812 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2813 ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr); 2814 ierr = PetscCalloc1(depth_, §ions_);CHKERRQ(ierr); 2815 arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2816 for (d=depth_-1; d>=0; d--) { 2817 ierr = PetscSectionCreate(PETSC_COMM_SELF, §ions_[d]);CHKERRQ(ierr); 2818 ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr); 2819 for (i=0; i<n; i++) { 2820 ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr); 2821 if (arr[i] >= start && arr[i] < end) { 2822 ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr); 2823 ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr); 2824 } else { 2825 ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr); 2826 } 2827 } 2828 ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr); 2829 ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr); 2830 ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr); 2831 for (i=0; i<n; i++) { 2832 ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr); 2833 ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr); 2834 if (cn > 1) { 2835 ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr); 2836 ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr); 2837 } else { 2838 newarr[co] = arr[i]; 2839 } 2840 } 2841 ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr); 2842 arr = newarr; 2843 n = newn; 2844 } 2845 ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr); 2846 *depth = depth_; 2847 if (expandedPoints) *expandedPoints = expandedPoints_; 2848 else { 2849 for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);} 2850 ierr = PetscFree(expandedPoints_);CHKERRQ(ierr); 2851 } 2852 if (sections) *sections = sections_; 2853 else { 2854 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(§ions_[d]);CHKERRQ(ierr);} 2855 ierr = PetscFree(sections_);CHKERRQ(ierr); 2856 } 2857 PetscFunctionReturn(0); 2858 } 2859 2860 /*@ 2861 DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2862 2863 Not collective 2864 2865 Input Parameters: 2866 + dm - The DMPlex 2867 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2868 2869 Output Parameters: 2870 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2871 . expandedPoints - (optional) An array of recursively expanded cones 2872 - sections - (optional) An array of sections which describe mappings from points to their cone points 2873 2874 Level: advanced 2875 2876 Notes: 2877 See DMPlexGetConeRecursive() for details. 2878 2879 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2880 @*/ 2881 PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2882 { 2883 PetscInt d, depth_; 2884 PetscErrorCode ierr; 2885 2886 PetscFunctionBegin; 2887 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2888 PetscCheckFalse(depth && *depth != depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2889 if (depth) *depth = 0; 2890 if (expandedPoints) { 2891 for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);} 2892 ierr = PetscFree(*expandedPoints);CHKERRQ(ierr); 2893 } 2894 if (sections) { 2895 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);} 2896 ierr = PetscFree(*sections);CHKERRQ(ierr); 2897 } 2898 PetscFunctionReturn(0); 2899 } 2900 2901 /*@ 2902 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 2903 2904 Not collective 2905 2906 Input Parameters: 2907 + mesh - The DMPlex 2908 . p - The point, which must lie in the chart set with DMPlexSetChart() 2909 - cone - An array of points which are on the in-edges for point p 2910 2911 Output Parameter: 2912 2913 Note: 2914 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2915 2916 Level: beginner 2917 2918 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize() 2919 @*/ 2920 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 2921 { 2922 DM_Plex *mesh = (DM_Plex*) dm->data; 2923 PetscInt pStart, pEnd; 2924 PetscInt dof, off, c; 2925 PetscErrorCode ierr; 2926 2927 PetscFunctionBegin; 2928 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2929 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2930 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2931 if (dof) PetscValidPointer(cone, 3); 2932 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2933 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); 2934 for (c = 0; c < dof; ++c) { 2935 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); 2936 mesh->cones[off+c] = cone[c]; 2937 } 2938 PetscFunctionReturn(0); 2939 } 2940 2941 /*@C 2942 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 2943 2944 Not collective 2945 2946 Input Parameters: 2947 + mesh - The DMPlex 2948 - p - The point, which must lie in the chart set with DMPlexSetChart() 2949 2950 Output Parameter: 2951 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2952 integer giving the prescription for cone traversal. 2953 2954 Level: beginner 2955 2956 Notes: 2957 The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 2958 the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 2959 of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 2960 with the identity. 2961 2962 Fortran Notes: 2963 Since it returns an array, this routine is only available in Fortran 90, and you must 2964 include petsc.h90 in your code. 2965 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 2966 DMPlexRestoreConeOrientation() is not needed/available in C. 2967 2968 .seealso: DMPolytopeTypeComposeOrientation(), DMPolytopeTypeComposeOrientationInv(), DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 2969 @*/ 2970 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 2971 { 2972 DM_Plex *mesh = (DM_Plex*) dm->data; 2973 PetscInt off; 2974 PetscErrorCode ierr; 2975 2976 PetscFunctionBegin; 2977 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2978 if (PetscDefined(USE_DEBUG)) { 2979 PetscInt dof; 2980 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2981 if (dof) PetscValidPointer(coneOrientation, 3); 2982 } 2983 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2984 2985 *coneOrientation = &mesh->coneOrientations[off]; 2986 PetscFunctionReturn(0); 2987 } 2988 2989 /*@ 2990 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 2991 2992 Not collective 2993 2994 Input Parameters: 2995 + mesh - The DMPlex 2996 . p - The point, which must lie in the chart set with DMPlexSetChart() 2997 - coneOrientation - An array of orientations 2998 Output Parameter: 2999 3000 Notes: 3001 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 3002 3003 The meaning of coneOrientation is detailed in DMPlexGetConeOrientation(). 3004 3005 Level: beginner 3006 3007 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3008 @*/ 3009 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3010 { 3011 DM_Plex *mesh = (DM_Plex*) dm->data; 3012 PetscInt pStart, pEnd; 3013 PetscInt dof, off, c; 3014 PetscErrorCode ierr; 3015 3016 PetscFunctionBegin; 3017 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3018 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3019 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3020 if (dof) PetscValidPointer(coneOrientation, 3); 3021 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3022 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); 3023 for (c = 0; c < dof; ++c) { 3024 PetscInt cdof, o = coneOrientation[c]; 3025 3026 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 3027 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); 3028 mesh->coneOrientations[off+c] = o; 3029 } 3030 PetscFunctionReturn(0); 3031 } 3032 3033 /*@ 3034 DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 3035 3036 Not collective 3037 3038 Input Parameters: 3039 + mesh - The DMPlex 3040 . p - The point, which must lie in the chart set with DMPlexSetChart() 3041 . conePos - The local index in the cone where the point should be put 3042 - conePoint - The mesh point to insert 3043 3044 Level: beginner 3045 3046 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3047 @*/ 3048 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3049 { 3050 DM_Plex *mesh = (DM_Plex*) dm->data; 3051 PetscInt pStart, pEnd; 3052 PetscInt dof, off; 3053 PetscErrorCode ierr; 3054 3055 PetscFunctionBegin; 3056 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3057 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3058 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); 3059 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); 3060 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3061 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3062 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); 3063 mesh->cones[off+conePos] = conePoint; 3064 PetscFunctionReturn(0); 3065 } 3066 3067 /*@ 3068 DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 3069 3070 Not collective 3071 3072 Input Parameters: 3073 + mesh - The DMPlex 3074 . p - The point, which must lie in the chart set with DMPlexSetChart() 3075 . conePos - The local index in the cone where the point should be put 3076 - coneOrientation - The point orientation to insert 3077 3078 Level: beginner 3079 3080 Notes: 3081 The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation(). 3082 3083 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3084 @*/ 3085 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3086 { 3087 DM_Plex *mesh = (DM_Plex*) dm->data; 3088 PetscInt pStart, pEnd; 3089 PetscInt dof, off; 3090 PetscErrorCode ierr; 3091 3092 PetscFunctionBegin; 3093 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3094 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3095 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); 3096 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3097 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3098 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); 3099 mesh->coneOrientations[off+conePos] = coneOrientation; 3100 PetscFunctionReturn(0); 3101 } 3102 3103 /*@ 3104 DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3105 3106 Not collective 3107 3108 Input Parameters: 3109 + mesh - The DMPlex 3110 - p - The point, which must lie in the chart set with DMPlexSetChart() 3111 3112 Output Parameter: 3113 . size - The support size for point p 3114 3115 Level: beginner 3116 3117 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 3118 @*/ 3119 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3120 { 3121 DM_Plex *mesh = (DM_Plex*) dm->data; 3122 PetscErrorCode ierr; 3123 3124 PetscFunctionBegin; 3125 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3126 PetscValidPointer(size, 3); 3127 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3128 PetscFunctionReturn(0); 3129 } 3130 3131 /*@ 3132 DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3133 3134 Not collective 3135 3136 Input Parameters: 3137 + mesh - The DMPlex 3138 . p - The point, which must lie in the chart set with DMPlexSetChart() 3139 - size - The support size for point p 3140 3141 Output Parameter: 3142 3143 Note: 3144 This should be called after DMPlexSetChart(). 3145 3146 Level: beginner 3147 3148 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 3149 @*/ 3150 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3151 { 3152 DM_Plex *mesh = (DM_Plex*) dm->data; 3153 PetscErrorCode ierr; 3154 3155 PetscFunctionBegin; 3156 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3157 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3158 3159 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 3160 PetscFunctionReturn(0); 3161 } 3162 3163 /*@C 3164 DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3165 3166 Not collective 3167 3168 Input Parameters: 3169 + mesh - The DMPlex 3170 - p - The point, which must lie in the chart set with DMPlexSetChart() 3171 3172 Output Parameter: 3173 . support - An array of points which are on the out-edges for point p 3174 3175 Level: beginner 3176 3177 Fortran Notes: 3178 Since it returns an array, this routine is only available in Fortran 90, and you must 3179 include petsc.h90 in your code. 3180 You must also call DMPlexRestoreSupport() after you finish using the returned array. 3181 DMPlexRestoreSupport() is not needed/available in C. 3182 3183 .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart() 3184 @*/ 3185 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3186 { 3187 DM_Plex *mesh = (DM_Plex*) dm->data; 3188 PetscInt off; 3189 PetscErrorCode ierr; 3190 3191 PetscFunctionBegin; 3192 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3193 PetscValidPointer(support, 3); 3194 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3195 *support = &mesh->supports[off]; 3196 PetscFunctionReturn(0); 3197 } 3198 3199 /*@ 3200 DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 3201 3202 Not collective 3203 3204 Input Parameters: 3205 + mesh - The DMPlex 3206 . p - The point, which must lie in the chart set with DMPlexSetChart() 3207 - support - An array of points which are on the out-edges for point p 3208 3209 Output Parameter: 3210 3211 Note: 3212 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 3213 3214 Level: beginner 3215 3216 .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 3217 @*/ 3218 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3219 { 3220 DM_Plex *mesh = (DM_Plex*) dm->data; 3221 PetscInt pStart, pEnd; 3222 PetscInt dof, off, c; 3223 PetscErrorCode ierr; 3224 3225 PetscFunctionBegin; 3226 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3227 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3228 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3229 if (dof) PetscValidPointer(support, 3); 3230 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3231 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); 3232 for (c = 0; c < dof; ++c) { 3233 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); 3234 mesh->supports[off+c] = support[c]; 3235 } 3236 PetscFunctionReturn(0); 3237 } 3238 3239 /*@ 3240 DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 3241 3242 Not collective 3243 3244 Input Parameters: 3245 + mesh - The DMPlex 3246 . p - The point, which must lie in the chart set with DMPlexSetChart() 3247 . supportPos - The local index in the cone where the point should be put 3248 - supportPoint - The mesh point to insert 3249 3250 Level: beginner 3251 3252 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3253 @*/ 3254 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3255 { 3256 DM_Plex *mesh = (DM_Plex*) dm->data; 3257 PetscInt pStart, pEnd; 3258 PetscInt dof, off; 3259 PetscErrorCode ierr; 3260 3261 PetscFunctionBegin; 3262 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3263 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3264 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3265 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3266 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); 3267 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); 3268 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); 3269 mesh->supports[off+supportPos] = supportPoint; 3270 PetscFunctionReturn(0); 3271 } 3272 3273 /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3274 PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3275 { 3276 switch (ct) { 3277 case DM_POLYTOPE_SEGMENT: 3278 if (o == -1) return -2; 3279 break; 3280 case DM_POLYTOPE_TRIANGLE: 3281 if (o == -3) return -1; 3282 if (o == -2) return -3; 3283 if (o == -1) return -2; 3284 break; 3285 case DM_POLYTOPE_QUADRILATERAL: 3286 if (o == -4) return -2; 3287 if (o == -3) return -1; 3288 if (o == -2) return -4; 3289 if (o == -1) return -3; 3290 break; 3291 default: return o; 3292 } 3293 return o; 3294 } 3295 3296 /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3297 PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3298 { 3299 switch (ct) { 3300 case DM_POLYTOPE_SEGMENT: 3301 if ((o == -2) || (o == 1)) return -1; 3302 if (o == -1) return 0; 3303 break; 3304 case DM_POLYTOPE_TRIANGLE: 3305 if (o == -3) return -2; 3306 if (o == -2) return -1; 3307 if (o == -1) return -3; 3308 break; 3309 case DM_POLYTOPE_QUADRILATERAL: 3310 if (o == -4) return -2; 3311 if (o == -3) return -1; 3312 if (o == -2) return -4; 3313 if (o == -1) return -3; 3314 break; 3315 default: return o; 3316 } 3317 return o; 3318 } 3319 3320 /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3321 PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3322 { 3323 PetscInt pStart, pEnd, p; 3324 PetscErrorCode ierr; 3325 3326 PetscFunctionBegin; 3327 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3328 for (p = pStart; p < pEnd; ++p) { 3329 const PetscInt *cone, *ornt; 3330 PetscInt coneSize, c; 3331 3332 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3333 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 3334 ierr = DMPlexGetConeOrientation(dm, p, &ornt);CHKERRQ(ierr); 3335 for (c = 0; c < coneSize; ++c) { 3336 DMPolytopeType ct; 3337 const PetscInt o = ornt[c]; 3338 3339 ierr = DMPlexGetCellType(dm, cone[c], &ct);CHKERRQ(ierr); 3340 switch (ct) { 3341 case DM_POLYTOPE_SEGMENT: 3342 if ((o == -2) || (o == 1)) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3343 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, 0);CHKERRQ(ierr);} 3344 break; 3345 case DM_POLYTOPE_TRIANGLE: 3346 if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);} 3347 if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3348 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);} 3349 break; 3350 case DM_POLYTOPE_QUADRILATERAL: 3351 if (o == -4) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);} 3352 if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3353 if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -4);CHKERRQ(ierr);} 3354 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);} 3355 break; 3356 default: break; 3357 } 3358 } 3359 } 3360 PetscFunctionReturn(0); 3361 } 3362 3363 static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3364 { 3365 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3366 PetscInt *closure; 3367 const PetscInt *tmp = NULL, *tmpO = NULL; 3368 PetscInt off = 0, tmpSize, t; 3369 PetscErrorCode ierr; 3370 3371 PetscFunctionBeginHot; 3372 if (ornt) { 3373 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3374 if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3375 } 3376 if (*points) { 3377 closure = *points; 3378 } else { 3379 PetscInt maxConeSize, maxSupportSize; 3380 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3381 ierr = DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure);CHKERRQ(ierr); 3382 } 3383 if (useCone) { 3384 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 3385 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 3386 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 3387 } else { 3388 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 3389 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 3390 } 3391 if (ct == DM_POLYTOPE_UNKNOWN) { 3392 closure[off++] = p; 3393 closure[off++] = 0; 3394 for (t = 0; t < tmpSize; ++t) { 3395 closure[off++] = tmp[t]; 3396 closure[off++] = tmpO ? tmpO[t] : 0; 3397 } 3398 } else { 3399 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);CHKERRQ(ierr); 3400 3401 /* We assume that cells with a valid type have faces with a valid type */ 3402 closure[off++] = p; 3403 closure[off++] = ornt; 3404 for (t = 0; t < tmpSize; ++t) { 3405 DMPolytopeType ft; 3406 3407 ierr = DMPlexGetCellType(dm, tmp[t], &ft);CHKERRQ(ierr); 3408 closure[off++] = tmp[arr[t]]; 3409 closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3410 } 3411 } 3412 if (numPoints) *numPoints = tmpSize+1; 3413 if (points) *points = closure; 3414 PetscFunctionReturn(0); 3415 } 3416 3417 /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */ 3418 static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3419 { 3420 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3421 const PetscInt *cone, *ornt; 3422 PetscInt *pts, *closure = NULL; 3423 DMPolytopeType ft; 3424 PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3425 PetscInt dim, coneSize, c, d, clSize, cl; 3426 PetscErrorCode ierr; 3427 3428 PetscFunctionBeginHot; 3429 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3430 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 3431 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3432 ierr = DMPlexGetConeOrientation(dm, point, &ornt);CHKERRQ(ierr); 3433 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3434 coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim+1)-1)/(maxConeSize-1)) : dim+1; 3435 supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1; 3436 maxSize = PetscMax(coneSeries, supportSeries); 3437 if (*points) {pts = *points;} 3438 else {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts);CHKERRQ(ierr);} 3439 c = 0; 3440 pts[c++] = point; 3441 pts[c++] = o; 3442 ierr = DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft);CHKERRQ(ierr); 3443 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure);CHKERRQ(ierr); 3444 for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 3445 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure);CHKERRQ(ierr); 3446 for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 3447 ierr = DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure);CHKERRQ(ierr); 3448 for (d = 2; d < coneSize; ++d) { 3449 ierr = DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft);CHKERRQ(ierr); 3450 pts[c++] = cone[arr[d*2+0]]; 3451 pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]); 3452 } 3453 if (dim >= 3) { 3454 for (d = 2; d < coneSize; ++d) { 3455 const PetscInt fpoint = cone[arr[d*2+0]]; 3456 const PetscInt *fcone, *fornt; 3457 PetscInt fconeSize, fc, i; 3458 3459 ierr = DMPlexGetCellType(dm, fpoint, &ft);CHKERRQ(ierr); 3460 const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d])); 3461 ierr = DMPlexGetConeSize(dm, fpoint, &fconeSize);CHKERRQ(ierr); 3462 ierr = DMPlexGetCone(dm, fpoint, &fcone);CHKERRQ(ierr); 3463 ierr = DMPlexGetConeOrientation(dm, fpoint, &fornt);CHKERRQ(ierr); 3464 for (fc = 0; fc < fconeSize; ++fc) { 3465 const PetscInt cp = fcone[farr[fc*2+0]]; 3466 const PetscInt co = farr[fc*2+1]; 3467 3468 for (i = 0; i < c; i += 2) if (pts[i] == cp) break; 3469 if (i == c) { 3470 ierr = DMPlexGetCellType(dm, cp, &ft);CHKERRQ(ierr); 3471 pts[c++] = cp; 3472 pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]); 3473 } 3474 } 3475 } 3476 } 3477 *numPoints = c/2; 3478 *points = pts; 3479 PetscFunctionReturn(0); 3480 } 3481 3482 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3483 { 3484 DMPolytopeType ct; 3485 PetscInt *closure, *fifo; 3486 PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3487 PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3488 PetscInt depth, maxSize; 3489 PetscErrorCode ierr; 3490 3491 PetscFunctionBeginHot; 3492 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3493 if (depth == 1) { 3494 ierr = DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points);CHKERRQ(ierr); 3495 PetscFunctionReturn(0); 3496 } 3497 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3498 if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3499 if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 3500 ierr = DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points);CHKERRQ(ierr); 3501 PetscFunctionReturn(0); 3502 } 3503 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3504 coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth+1)-1)/(maxConeSize-1)) : depth+1; 3505 supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1; 3506 maxSize = PetscMax(coneSeries, supportSeries); 3507 ierr = DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3508 if (*points) {closure = *points;} 3509 else {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure);CHKERRQ(ierr);} 3510 closure[closureSize++] = p; 3511 closure[closureSize++] = ornt; 3512 fifo[fifoSize++] = p; 3513 fifo[fifoSize++] = ornt; 3514 fifo[fifoSize++] = ct; 3515 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3516 while (fifoSize - fifoStart) { 3517 const PetscInt q = fifo[fifoStart++]; 3518 const PetscInt o = fifo[fifoStart++]; 3519 const DMPolytopeType qt = (DMPolytopeType) fifo[fifoStart++]; 3520 const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 3521 const PetscInt *tmp, *tmpO; 3522 PetscInt tmpSize, t; 3523 3524 if (PetscDefined(USE_DEBUG)) { 3525 PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2; 3526 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); 3527 } 3528 if (useCone) { 3529 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 3530 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 3531 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 3532 } else { 3533 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 3534 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 3535 tmpO = NULL; 3536 } 3537 for (t = 0; t < tmpSize; ++t) { 3538 const PetscInt ip = useCone && qarr ? qarr[t*2] : t; 3539 const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0; 3540 const PetscInt cp = tmp[ip]; 3541 ierr = DMPlexGetCellType(dm, cp, &ct);CHKERRQ(ierr); 3542 const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3543 PetscInt c; 3544 3545 /* Check for duplicate */ 3546 for (c = 0; c < closureSize; c += 2) { 3547 if (closure[c] == cp) break; 3548 } 3549 if (c == closureSize) { 3550 closure[closureSize++] = cp; 3551 closure[closureSize++] = co; 3552 fifo[fifoSize++] = cp; 3553 fifo[fifoSize++] = co; 3554 fifo[fifoSize++] = ct; 3555 } 3556 } 3557 } 3558 ierr = DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3559 if (numPoints) *numPoints = closureSize/2; 3560 if (points) *points = closure; 3561 PetscFunctionReturn(0); 3562 } 3563 3564 /*@C 3565 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3566 3567 Not collective 3568 3569 Input Parameters: 3570 + dm - The DMPlex 3571 . p - The mesh point 3572 - useCone - PETSC_TRUE for the closure, otherwise return the star 3573 3574 Input/Output Parameter: 3575 . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 3576 if NULL on input, internal storage will be returned, otherwise the provided array is used 3577 3578 Output Parameter: 3579 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3580 3581 Note: 3582 If using internal storage (points is NULL on input), each call overwrites the last output. 3583 3584 Fortran Notes: 3585 Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3586 3587 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3588 3589 Level: beginner 3590 3591 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3592 @*/ 3593 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3594 { 3595 PetscErrorCode ierr; 3596 3597 PetscFunctionBeginHot; 3598 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3599 if (numPoints) PetscValidIntPointer(numPoints, 4); 3600 if (points) PetscValidPointer(points, 5); 3601 ierr = DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points);CHKERRQ(ierr); 3602 PetscFunctionReturn(0); 3603 } 3604 3605 /*@C 3606 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3607 3608 Not collective 3609 3610 Input Parameters: 3611 + dm - The DMPlex 3612 . p - The mesh point 3613 . useCone - PETSC_TRUE for the closure, otherwise return the star 3614 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3615 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3616 3617 Note: 3618 If not using internal storage (points is not NULL on input), this call is unnecessary 3619 3620 Fortran Notes: 3621 Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3622 3623 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3624 3625 Level: beginner 3626 3627 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3628 @*/ 3629 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3630 { 3631 PetscErrorCode ierr; 3632 3633 PetscFunctionBeginHot; 3634 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3635 if (numPoints) *numPoints = 0; 3636 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr); 3637 PetscFunctionReturn(0); 3638 } 3639 3640 /*@ 3641 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3642 3643 Not collective 3644 3645 Input Parameter: 3646 . mesh - The DMPlex 3647 3648 Output Parameters: 3649 + maxConeSize - The maximum number of in-edges 3650 - maxSupportSize - The maximum number of out-edges 3651 3652 Level: beginner 3653 3654 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 3655 @*/ 3656 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3657 { 3658 DM_Plex *mesh = (DM_Plex*) dm->data; 3659 3660 PetscFunctionBegin; 3661 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3662 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 3663 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 3664 PetscFunctionReturn(0); 3665 } 3666 3667 PetscErrorCode DMSetUp_Plex(DM dm) 3668 { 3669 DM_Plex *mesh = (DM_Plex*) dm->data; 3670 PetscInt size; 3671 PetscErrorCode ierr; 3672 3673 PetscFunctionBegin; 3674 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3675 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 3676 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 3677 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 3678 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 3679 ierr = PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt));CHKERRQ(ierr); 3680 if (mesh->maxSupportSize) { 3681 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3682 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 3683 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 3684 ierr = PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt));CHKERRQ(ierr); 3685 } 3686 PetscFunctionReturn(0); 3687 } 3688 3689 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3690 { 3691 PetscErrorCode ierr; 3692 3693 PetscFunctionBegin; 3694 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 3695 ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 3696 if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3697 if (dm->useNatural && dm->sfMigration) { 3698 PetscSF sfMigrationInv,sfNatural; 3699 PetscSection section, sectionSeq; 3700 3701 (*subdm)->sfMigration = dm->sfMigration; 3702 ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr); 3703 ierr = DMGetLocalSection((*subdm), §ion);CHKERRQ(ierr); 3704 ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3705 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq);CHKERRQ(ierr); 3706 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3707 3708 ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3709 (*subdm)->sfNatural = sfNatural; 3710 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3711 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3712 } 3713 PetscFunctionReturn(0); 3714 } 3715 3716 PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 3717 { 3718 PetscErrorCode ierr; 3719 PetscInt i = 0; 3720 3721 PetscFunctionBegin; 3722 ierr = DMClone(dms[0], superdm);CHKERRQ(ierr); 3723 ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr); 3724 (*superdm)->useNatural = PETSC_FALSE; 3725 for (i = 0; i < len; i++) { 3726 if (dms[i]->useNatural && dms[i]->sfMigration) { 3727 PetscSF sfMigrationInv,sfNatural; 3728 PetscSection section, sectionSeq; 3729 3730 (*superdm)->sfMigration = dms[i]->sfMigration; 3731 ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr); 3732 (*superdm)->useNatural = PETSC_TRUE; 3733 ierr = DMGetLocalSection((*superdm), §ion);CHKERRQ(ierr); 3734 ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3735 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq);CHKERRQ(ierr); 3736 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3737 3738 ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3739 (*superdm)->sfNatural = sfNatural; 3740 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3741 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3742 break; 3743 } 3744 } 3745 PetscFunctionReturn(0); 3746 } 3747 3748 /*@ 3749 DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3750 3751 Not collective 3752 3753 Input Parameter: 3754 . mesh - The DMPlex 3755 3756 Output Parameter: 3757 3758 Note: 3759 This should be called after all calls to DMPlexSetCone() 3760 3761 Level: beginner 3762 3763 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 3764 @*/ 3765 PetscErrorCode DMPlexSymmetrize(DM dm) 3766 { 3767 DM_Plex *mesh = (DM_Plex*) dm->data; 3768 PetscInt *offsets; 3769 PetscInt supportSize; 3770 PetscInt pStart, pEnd, p; 3771 PetscErrorCode ierr; 3772 3773 PetscFunctionBegin; 3774 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3775 PetscCheckFalse(mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 3776 ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3777 /* Calculate support sizes */ 3778 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3779 for (p = pStart; p < pEnd; ++p) { 3780 PetscInt dof, off, c; 3781 3782 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3783 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3784 for (c = off; c < off+dof; ++c) { 3785 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 3786 } 3787 } 3788 for (p = pStart; p < pEnd; ++p) { 3789 PetscInt dof; 3790 3791 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3792 3793 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 3794 } 3795 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3796 /* Calculate supports */ 3797 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 3798 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 3799 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 3800 for (p = pStart; p < pEnd; ++p) { 3801 PetscInt dof, off, c; 3802 3803 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3804 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3805 for (c = off; c < off+dof; ++c) { 3806 const PetscInt q = mesh->cones[c]; 3807 PetscInt offS; 3808 3809 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 3810 3811 mesh->supports[offS+offsets[q]] = p; 3812 ++offsets[q]; 3813 } 3814 } 3815 ierr = PetscFree(offsets);CHKERRQ(ierr); 3816 ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3817 PetscFunctionReturn(0); 3818 } 3819 3820 static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3821 { 3822 IS stratumIS; 3823 PetscErrorCode ierr; 3824 3825 PetscFunctionBegin; 3826 if (pStart >= pEnd) PetscFunctionReturn(0); 3827 if (PetscDefined(USE_DEBUG)) { 3828 PetscInt qStart, qEnd, numLevels, level; 3829 PetscBool overlap = PETSC_FALSE; 3830 ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr); 3831 for (level = 0; level < numLevels; level++) { 3832 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3833 if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3834 } 3835 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); 3836 } 3837 ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr); 3838 ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr); 3839 ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 3840 PetscFunctionReturn(0); 3841 } 3842 3843 /*@ 3844 DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 3845 can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3846 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3847 the DAG. 3848 3849 Collective on dm 3850 3851 Input Parameter: 3852 . mesh - The DMPlex 3853 3854 Output Parameter: 3855 3856 Notes: 3857 Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3858 meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 3859 until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3860 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3861 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3862 3863 The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3864 if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3865 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 3866 to interpolate only that one (e0), so that 3867 $ cone(c0) = {e0, v2} 3868 $ cone(e0) = {v0, v1} 3869 If DMPlexStratify() is run on this mesh, it will give depths 3870 $ depth 0 = {v0, v1, v2} 3871 $ depth 1 = {e0, c0} 3872 where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3873 3874 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3875 3876 Level: beginner 3877 3878 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes() 3879 @*/ 3880 PetscErrorCode DMPlexStratify(DM dm) 3881 { 3882 DM_Plex *mesh = (DM_Plex*) dm->data; 3883 DMLabel label; 3884 PetscInt pStart, pEnd, p; 3885 PetscInt numRoots = 0, numLeaves = 0; 3886 PetscErrorCode ierr; 3887 3888 PetscFunctionBegin; 3889 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3890 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3891 3892 /* Create depth label */ 3893 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3894 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 3895 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3896 3897 { 3898 /* Initialize roots and count leaves */ 3899 PetscInt sMin = PETSC_MAX_INT; 3900 PetscInt sMax = PETSC_MIN_INT; 3901 PetscInt coneSize, supportSize; 3902 3903 for (p = pStart; p < pEnd; ++p) { 3904 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3905 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3906 if (!coneSize && supportSize) { 3907 sMin = PetscMin(p, sMin); 3908 sMax = PetscMax(p, sMax); 3909 ++numRoots; 3910 } else if (!supportSize && coneSize) { 3911 ++numLeaves; 3912 } else if (!supportSize && !coneSize) { 3913 /* Isolated points */ 3914 sMin = PetscMin(p, sMin); 3915 sMax = PetscMax(p, sMax); 3916 } 3917 } 3918 ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr); 3919 } 3920 3921 if (numRoots + numLeaves == (pEnd - pStart)) { 3922 PetscInt sMin = PETSC_MAX_INT; 3923 PetscInt sMax = PETSC_MIN_INT; 3924 PetscInt coneSize, supportSize; 3925 3926 for (p = pStart; p < pEnd; ++p) { 3927 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3928 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3929 if (!supportSize && coneSize) { 3930 sMin = PetscMin(p, sMin); 3931 sMax = PetscMax(p, sMax); 3932 } 3933 } 3934 ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr); 3935 } else { 3936 PetscInt level = 0; 3937 PetscInt qStart, qEnd, q; 3938 3939 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3940 while (qEnd > qStart) { 3941 PetscInt sMin = PETSC_MAX_INT; 3942 PetscInt sMax = PETSC_MIN_INT; 3943 3944 for (q = qStart; q < qEnd; ++q) { 3945 const PetscInt *support; 3946 PetscInt supportSize, s; 3947 3948 ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr); 3949 ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr); 3950 for (s = 0; s < supportSize; ++s) { 3951 sMin = PetscMin(support[s], sMin); 3952 sMax = PetscMax(support[s], sMax); 3953 } 3954 } 3955 ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr); 3956 ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr); 3957 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3958 } 3959 } 3960 { /* just in case there is an empty process */ 3961 PetscInt numValues, maxValues = 0, v; 3962 3963 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 3964 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 3965 for (v = numValues; v < maxValues; v++) { 3966 ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr); 3967 } 3968 } 3969 ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr); 3970 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3971 PetscFunctionReturn(0); 3972 } 3973 3974 PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 3975 { 3976 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3977 PetscInt dim, depth, pheight, coneSize; 3978 PetscErrorCode ierr; 3979 3980 PetscFunctionBeginHot; 3981 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3982 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3983 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3984 pheight = depth - pdepth; 3985 if (depth <= 1) { 3986 switch (pdepth) { 3987 case 0: ct = DM_POLYTOPE_POINT;break; 3988 case 1: 3989 switch (coneSize) { 3990 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3991 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3992 case 4: 3993 switch (dim) { 3994 case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 3995 case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 3996 default: break; 3997 } 3998 break; 3999 case 5: ct = DM_POLYTOPE_PYRAMID;break; 4000 case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4001 case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 4002 default: break; 4003 } 4004 } 4005 } else { 4006 if (pdepth == 0) { 4007 ct = DM_POLYTOPE_POINT; 4008 } else if (pheight == 0) { 4009 switch (dim) { 4010 case 1: 4011 switch (coneSize) { 4012 case 2: ct = DM_POLYTOPE_SEGMENT;break; 4013 default: break; 4014 } 4015 break; 4016 case 2: 4017 switch (coneSize) { 4018 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4019 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4020 default: break; 4021 } 4022 break; 4023 case 3: 4024 switch (coneSize) { 4025 case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 4026 case 5: 4027 { 4028 const PetscInt *cone; 4029 PetscInt faceConeSize; 4030 4031 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 4032 ierr = DMPlexGetConeSize(dm, cone[0], &faceConeSize);CHKERRQ(ierr); 4033 switch (faceConeSize) { 4034 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4035 case 4: ct = DM_POLYTOPE_PYRAMID;break; 4036 } 4037 } 4038 break; 4039 case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 4040 default: break; 4041 } 4042 break; 4043 default: break; 4044 } 4045 } else if (pheight > 0) { 4046 switch (coneSize) { 4047 case 2: ct = DM_POLYTOPE_SEGMENT;break; 4048 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4049 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4050 default: break; 4051 } 4052 } 4053 } 4054 *pt = ct; 4055 PetscFunctionReturn(0); 4056 } 4057 4058 /*@ 4059 DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4060 4061 Collective on dm 4062 4063 Input Parameter: 4064 . mesh - The DMPlex 4065 4066 DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 4067 4068 Level: developer 4069 4070 Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 4071 internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 4072 automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 4073 4074 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel() 4075 @*/ 4076 PetscErrorCode DMPlexComputeCellTypes(DM dm) 4077 { 4078 DM_Plex *mesh; 4079 DMLabel ctLabel; 4080 PetscInt pStart, pEnd, p; 4081 PetscErrorCode ierr; 4082 4083 PetscFunctionBegin; 4084 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4085 mesh = (DM_Plex *) dm->data; 4086 ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr); 4087 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 4088 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4089 for (p = pStart; p < pEnd; ++p) { 4090 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4091 PetscInt pdepth; 4092 4093 ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr); 4094 ierr = DMPlexComputeCellType_Internal(dm, p, pdepth, &ct);CHKERRQ(ierr); 4095 PetscCheckFalse(ct == DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p); 4096 ierr = DMLabelSetValue(ctLabel, p, ct);CHKERRQ(ierr); 4097 } 4098 ierr = PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState);CHKERRQ(ierr); 4099 ierr = PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr); 4100 PetscFunctionReturn(0); 4101 } 4102 4103 /*@C 4104 DMPlexGetJoin - Get an array for the join of the set of points 4105 4106 Not Collective 4107 4108 Input Parameters: 4109 + dm - The DMPlex object 4110 . numPoints - The number of input points for the join 4111 - points - The input points 4112 4113 Output Parameters: 4114 + numCoveredPoints - The number of points in the join 4115 - coveredPoints - The points in the join 4116 4117 Level: intermediate 4118 4119 Note: Currently, this is restricted to a single level join 4120 4121 Fortran Notes: 4122 Since it returns an array, this routine is only available in Fortran 90, and you must 4123 include petsc.h90 in your code. 4124 4125 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4126 4127 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 4128 @*/ 4129 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4130 { 4131 DM_Plex *mesh = (DM_Plex*) dm->data; 4132 PetscInt *join[2]; 4133 PetscInt joinSize, i = 0; 4134 PetscInt dof, off, p, c, m; 4135 PetscErrorCode ierr; 4136 4137 PetscFunctionBegin; 4138 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4139 PetscValidIntPointer(points, 3); 4140 PetscValidIntPointer(numCoveredPoints, 4); 4141 PetscValidPointer(coveredPoints, 5); 4142 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4143 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4144 /* Copy in support of first point */ 4145 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 4146 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 4147 for (joinSize = 0; joinSize < dof; ++joinSize) { 4148 join[i][joinSize] = mesh->supports[off+joinSize]; 4149 } 4150 /* Check each successive support */ 4151 for (p = 1; p < numPoints; ++p) { 4152 PetscInt newJoinSize = 0; 4153 4154 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 4155 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 4156 for (c = 0; c < dof; ++c) { 4157 const PetscInt point = mesh->supports[off+c]; 4158 4159 for (m = 0; m < joinSize; ++m) { 4160 if (point == join[i][m]) { 4161 join[1-i][newJoinSize++] = point; 4162 break; 4163 } 4164 } 4165 } 4166 joinSize = newJoinSize; 4167 i = 1-i; 4168 } 4169 *numCoveredPoints = joinSize; 4170 *coveredPoints = join[i]; 4171 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4172 PetscFunctionReturn(0); 4173 } 4174 4175 /*@C 4176 DMPlexRestoreJoin - Restore an array for the join of the set of points 4177 4178 Not Collective 4179 4180 Input Parameters: 4181 + dm - The DMPlex object 4182 . numPoints - The number of input points for the join 4183 - points - The input points 4184 4185 Output Parameters: 4186 + numCoveredPoints - The number of points in the join 4187 - coveredPoints - The points in the join 4188 4189 Fortran Notes: 4190 Since it returns an array, this routine is only available in Fortran 90, and you must 4191 include petsc.h90 in your code. 4192 4193 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4194 4195 Level: intermediate 4196 4197 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 4198 @*/ 4199 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4200 { 4201 PetscErrorCode ierr; 4202 4203 PetscFunctionBegin; 4204 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4205 if (points) PetscValidIntPointer(points,3); 4206 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4207 PetscValidPointer(coveredPoints, 5); 4208 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4209 if (numCoveredPoints) *numCoveredPoints = 0; 4210 PetscFunctionReturn(0); 4211 } 4212 4213 /*@C 4214 DMPlexGetFullJoin - Get an array for the join of the set of points 4215 4216 Not Collective 4217 4218 Input Parameters: 4219 + dm - The DMPlex object 4220 . numPoints - The number of input points for the join 4221 - points - The input points 4222 4223 Output Parameters: 4224 + numCoveredPoints - The number of points in the join 4225 - coveredPoints - The points in the join 4226 4227 Fortran Notes: 4228 Since it returns an array, this routine is only available in Fortran 90, and you must 4229 include petsc.h90 in your code. 4230 4231 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4232 4233 Level: intermediate 4234 4235 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 4236 @*/ 4237 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4238 { 4239 DM_Plex *mesh = (DM_Plex*) dm->data; 4240 PetscInt *offsets, **closures; 4241 PetscInt *join[2]; 4242 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 4243 PetscInt p, d, c, m, ms; 4244 PetscErrorCode ierr; 4245 4246 PetscFunctionBegin; 4247 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4248 PetscValidIntPointer(points, 3); 4249 PetscValidIntPointer(numCoveredPoints, 4); 4250 PetscValidPointer(coveredPoints, 5); 4251 4252 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4253 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 4254 ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4255 ms = mesh->maxSupportSize; 4256 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 4257 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4258 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4259 4260 for (p = 0; p < numPoints; ++p) { 4261 PetscInt closureSize; 4262 4263 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 4264 4265 offsets[p*(depth+2)+0] = 0; 4266 for (d = 0; d < depth+1; ++d) { 4267 PetscInt pStart, pEnd, i; 4268 4269 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 4270 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4271 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4272 offsets[p*(depth+2)+d+1] = i; 4273 break; 4274 } 4275 } 4276 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4277 } 4278 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); 4279 } 4280 for (d = 0; d < depth+1; ++d) { 4281 PetscInt dof; 4282 4283 /* Copy in support of first point */ 4284 dof = offsets[d+1] - offsets[d]; 4285 for (joinSize = 0; joinSize < dof; ++joinSize) { 4286 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4287 } 4288 /* Check each successive cone */ 4289 for (p = 1; p < numPoints && joinSize; ++p) { 4290 PetscInt newJoinSize = 0; 4291 4292 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4293 for (c = 0; c < dof; ++c) { 4294 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4295 4296 for (m = 0; m < joinSize; ++m) { 4297 if (point == join[i][m]) { 4298 join[1-i][newJoinSize++] = point; 4299 break; 4300 } 4301 } 4302 } 4303 joinSize = newJoinSize; 4304 i = 1-i; 4305 } 4306 if (joinSize) break; 4307 } 4308 *numCoveredPoints = joinSize; 4309 *coveredPoints = join[i]; 4310 for (p = 0; p < numPoints; ++p) { 4311 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 4312 } 4313 ierr = PetscFree(closures);CHKERRQ(ierr); 4314 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4315 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4316 PetscFunctionReturn(0); 4317 } 4318 4319 /*@C 4320 DMPlexGetMeet - Get an array for the meet of the set of points 4321 4322 Not Collective 4323 4324 Input Parameters: 4325 + dm - The DMPlex object 4326 . numPoints - The number of input points for the meet 4327 - points - The input points 4328 4329 Output Parameters: 4330 + numCoveredPoints - The number of points in the meet 4331 - coveredPoints - The points in the meet 4332 4333 Level: intermediate 4334 4335 Note: Currently, this is restricted to a single level meet 4336 4337 Fortran Notes: 4338 Since it returns an array, this routine is only available in Fortran 90, and you must 4339 include petsc.h90 in your code. 4340 4341 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4342 4343 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 4344 @*/ 4345 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4346 { 4347 DM_Plex *mesh = (DM_Plex*) dm->data; 4348 PetscInt *meet[2]; 4349 PetscInt meetSize, i = 0; 4350 PetscInt dof, off, p, c, m; 4351 PetscErrorCode ierr; 4352 4353 PetscFunctionBegin; 4354 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4355 PetscValidPointer(points, 3); 4356 PetscValidPointer(numCoveringPoints, 4); 4357 PetscValidPointer(coveringPoints, 5); 4358 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4359 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4360 /* Copy in cone of first point */ 4361 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 4362 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 4363 for (meetSize = 0; meetSize < dof; ++meetSize) { 4364 meet[i][meetSize] = mesh->cones[off+meetSize]; 4365 } 4366 /* Check each successive cone */ 4367 for (p = 1; p < numPoints; ++p) { 4368 PetscInt newMeetSize = 0; 4369 4370 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 4371 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 4372 for (c = 0; c < dof; ++c) { 4373 const PetscInt point = mesh->cones[off+c]; 4374 4375 for (m = 0; m < meetSize; ++m) { 4376 if (point == meet[i][m]) { 4377 meet[1-i][newMeetSize++] = point; 4378 break; 4379 } 4380 } 4381 } 4382 meetSize = newMeetSize; 4383 i = 1-i; 4384 } 4385 *numCoveringPoints = meetSize; 4386 *coveringPoints = meet[i]; 4387 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4388 PetscFunctionReturn(0); 4389 } 4390 4391 /*@C 4392 DMPlexRestoreMeet - Restore an array for the meet of the set of points 4393 4394 Not Collective 4395 4396 Input Parameters: 4397 + dm - The DMPlex object 4398 . numPoints - The number of input points for the meet 4399 - points - The input points 4400 4401 Output Parameters: 4402 + numCoveredPoints - The number of points in the meet 4403 - coveredPoints - The points in the meet 4404 4405 Level: intermediate 4406 4407 Fortran Notes: 4408 Since it returns an array, this routine is only available in Fortran 90, and you must 4409 include petsc.h90 in your code. 4410 4411 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4412 4413 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 4414 @*/ 4415 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4416 { 4417 PetscErrorCode ierr; 4418 4419 PetscFunctionBegin; 4420 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4421 if (points) PetscValidIntPointer(points,3); 4422 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4423 PetscValidPointer(coveredPoints,5); 4424 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4425 if (numCoveredPoints) *numCoveredPoints = 0; 4426 PetscFunctionReturn(0); 4427 } 4428 4429 /*@C 4430 DMPlexGetFullMeet - Get an array for the meet of the set of points 4431 4432 Not Collective 4433 4434 Input Parameters: 4435 + dm - The DMPlex object 4436 . numPoints - The number of input points for the meet 4437 - points - The input points 4438 4439 Output Parameters: 4440 + numCoveredPoints - The number of points in the meet 4441 - coveredPoints - The points in the meet 4442 4443 Level: intermediate 4444 4445 Fortran Notes: 4446 Since it returns an array, this routine is only available in Fortran 90, and you must 4447 include petsc.h90 in your code. 4448 4449 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4450 4451 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 4452 @*/ 4453 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4454 { 4455 DM_Plex *mesh = (DM_Plex*) dm->data; 4456 PetscInt *offsets, **closures; 4457 PetscInt *meet[2]; 4458 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 4459 PetscInt p, h, c, m, mc; 4460 PetscErrorCode ierr; 4461 4462 PetscFunctionBegin; 4463 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4464 PetscValidPointer(points, 3); 4465 PetscValidPointer(numCoveredPoints, 4); 4466 PetscValidPointer(coveredPoints, 5); 4467 4468 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 4469 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 4470 ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4471 mc = mesh->maxConeSize; 4472 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 4473 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4474 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4475 4476 for (p = 0; p < numPoints; ++p) { 4477 PetscInt closureSize; 4478 4479 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 4480 4481 offsets[p*(height+2)+0] = 0; 4482 for (h = 0; h < height+1; ++h) { 4483 PetscInt pStart, pEnd, i; 4484 4485 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 4486 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4487 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4488 offsets[p*(height+2)+h+1] = i; 4489 break; 4490 } 4491 } 4492 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4493 } 4494 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); 4495 } 4496 for (h = 0; h < height+1; ++h) { 4497 PetscInt dof; 4498 4499 /* Copy in cone of first point */ 4500 dof = offsets[h+1] - offsets[h]; 4501 for (meetSize = 0; meetSize < dof; ++meetSize) { 4502 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4503 } 4504 /* Check each successive cone */ 4505 for (p = 1; p < numPoints && meetSize; ++p) { 4506 PetscInt newMeetSize = 0; 4507 4508 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4509 for (c = 0; c < dof; ++c) { 4510 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4511 4512 for (m = 0; m < meetSize; ++m) { 4513 if (point == meet[i][m]) { 4514 meet[1-i][newMeetSize++] = point; 4515 break; 4516 } 4517 } 4518 } 4519 meetSize = newMeetSize; 4520 i = 1-i; 4521 } 4522 if (meetSize) break; 4523 } 4524 *numCoveredPoints = meetSize; 4525 *coveredPoints = meet[i]; 4526 for (p = 0; p < numPoints; ++p) { 4527 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 4528 } 4529 ierr = PetscFree(closures);CHKERRQ(ierr); 4530 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4531 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4532 PetscFunctionReturn(0); 4533 } 4534 4535 /*@C 4536 DMPlexEqual - Determine if two DMs have the same topology 4537 4538 Not Collective 4539 4540 Input Parameters: 4541 + dmA - A DMPlex object 4542 - dmB - A DMPlex object 4543 4544 Output Parameters: 4545 . equal - PETSC_TRUE if the topologies are identical 4546 4547 Level: intermediate 4548 4549 Notes: 4550 We are not solving graph isomorphism, so we do not permutation. 4551 4552 .seealso: DMPlexGetCone() 4553 @*/ 4554 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 4555 { 4556 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 4557 PetscErrorCode ierr; 4558 4559 PetscFunctionBegin; 4560 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 4561 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4562 PetscValidPointer(equal, 3); 4563 4564 *equal = PETSC_FALSE; 4565 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 4566 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 4567 if (depth != depthB) PetscFunctionReturn(0); 4568 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 4569 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 4570 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 4571 for (p = pStart; p < pEnd; ++p) { 4572 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 4573 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 4574 4575 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 4576 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 4577 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 4578 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 4579 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 4580 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 4581 if (coneSize != coneSizeB) PetscFunctionReturn(0); 4582 for (c = 0; c < coneSize; ++c) { 4583 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 4584 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 4585 } 4586 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 4587 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 4588 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 4589 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 4590 if (supportSize != supportSizeB) PetscFunctionReturn(0); 4591 for (s = 0; s < supportSize; ++s) { 4592 if (support[s] != supportB[s]) PetscFunctionReturn(0); 4593 } 4594 } 4595 *equal = PETSC_TRUE; 4596 PetscFunctionReturn(0); 4597 } 4598 4599 /*@C 4600 DMPlexGetNumFaceVertices - Returns the number of vertices on a face 4601 4602 Not Collective 4603 4604 Input Parameters: 4605 + dm - The DMPlex 4606 . cellDim - The cell dimension 4607 - numCorners - The number of vertices on a cell 4608 4609 Output Parameters: 4610 . numFaceVertices - The number of vertices on a face 4611 4612 Level: developer 4613 4614 Notes: 4615 Of course this can only work for a restricted set of symmetric shapes 4616 4617 .seealso: DMPlexGetCone() 4618 @*/ 4619 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4620 { 4621 MPI_Comm comm; 4622 PetscErrorCode ierr; 4623 4624 PetscFunctionBegin; 4625 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4626 PetscValidPointer(numFaceVertices,4); 4627 switch (cellDim) { 4628 case 0: 4629 *numFaceVertices = 0; 4630 break; 4631 case 1: 4632 *numFaceVertices = 1; 4633 break; 4634 case 2: 4635 switch (numCorners) { 4636 case 3: /* triangle */ 4637 *numFaceVertices = 2; /* Edge has 2 vertices */ 4638 break; 4639 case 4: /* quadrilateral */ 4640 *numFaceVertices = 2; /* Edge has 2 vertices */ 4641 break; 4642 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 4643 *numFaceVertices = 3; /* Edge has 3 vertices */ 4644 break; 4645 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 4646 *numFaceVertices = 3; /* Edge has 3 vertices */ 4647 break; 4648 default: 4649 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4650 } 4651 break; 4652 case 3: 4653 switch (numCorners) { 4654 case 4: /* tetradehdron */ 4655 *numFaceVertices = 3; /* Face has 3 vertices */ 4656 break; 4657 case 6: /* tet cohesive cells */ 4658 *numFaceVertices = 4; /* Face has 4 vertices */ 4659 break; 4660 case 8: /* hexahedron */ 4661 *numFaceVertices = 4; /* Face has 4 vertices */ 4662 break; 4663 case 9: /* tet cohesive Lagrange cells */ 4664 *numFaceVertices = 6; /* Face has 6 vertices */ 4665 break; 4666 case 10: /* quadratic tetrahedron */ 4667 *numFaceVertices = 6; /* Face has 6 vertices */ 4668 break; 4669 case 12: /* hex cohesive Lagrange cells */ 4670 *numFaceVertices = 6; /* Face has 6 vertices */ 4671 break; 4672 case 18: /* quadratic tet cohesive Lagrange cells */ 4673 *numFaceVertices = 6; /* Face has 6 vertices */ 4674 break; 4675 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 4676 *numFaceVertices = 9; /* Face has 9 vertices */ 4677 break; 4678 default: 4679 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4680 } 4681 break; 4682 default: 4683 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 4684 } 4685 PetscFunctionReturn(0); 4686 } 4687 4688 /*@ 4689 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4690 4691 Not Collective 4692 4693 Input Parameter: 4694 . dm - The DMPlex object 4695 4696 Output Parameter: 4697 . depthLabel - The DMLabel recording point depth 4698 4699 Level: developer 4700 4701 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), 4702 @*/ 4703 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4704 { 4705 PetscFunctionBegin; 4706 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4707 PetscValidPointer(depthLabel, 2); 4708 *depthLabel = dm->depthLabel; 4709 PetscFunctionReturn(0); 4710 } 4711 4712 /*@ 4713 DMPlexGetDepth - Get the depth of the DAG representing this mesh 4714 4715 Not Collective 4716 4717 Input Parameter: 4718 . dm - The DMPlex object 4719 4720 Output Parameter: 4721 . depth - The number of strata (breadth first levels) in the DAG 4722 4723 Level: developer 4724 4725 Notes: 4726 This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4727 The point depth is described more in detail in DMPlexGetDepthStratum(). 4728 An empty mesh gives -1. 4729 4730 .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize() 4731 @*/ 4732 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4733 { 4734 DMLabel label; 4735 PetscInt d = 0; 4736 PetscErrorCode ierr; 4737 4738 PetscFunctionBegin; 4739 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4740 PetscValidPointer(depth, 2); 4741 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4742 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 4743 *depth = d-1; 4744 PetscFunctionReturn(0); 4745 } 4746 4747 /*@ 4748 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4749 4750 Not Collective 4751 4752 Input Parameters: 4753 + dm - The DMPlex object 4754 - stratumValue - The requested depth 4755 4756 Output Parameters: 4757 + start - The first point at this depth 4758 - end - One beyond the last point at this depth 4759 4760 Notes: 4761 Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4762 often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4763 higher dimension, e.g., "edges". 4764 4765 Level: developer 4766 4767 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate() 4768 @*/ 4769 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4770 { 4771 DMLabel label; 4772 PetscInt pStart, pEnd; 4773 PetscErrorCode ierr; 4774 4775 PetscFunctionBegin; 4776 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4777 if (start) {PetscValidPointer(start, 3); *start = 0;} 4778 if (end) {PetscValidPointer(end, 4); *end = 0;} 4779 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4780 if (pStart == pEnd) PetscFunctionReturn(0); 4781 if (stratumValue < 0) { 4782 if (start) *start = pStart; 4783 if (end) *end = pEnd; 4784 PetscFunctionReturn(0); 4785 } 4786 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4787 PetscCheckFalse(!label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4788 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 4789 PetscFunctionReturn(0); 4790 } 4791 4792 /*@ 4793 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4794 4795 Not Collective 4796 4797 Input Parameters: 4798 + dm - The DMPlex object 4799 - stratumValue - The requested height 4800 4801 Output Parameters: 4802 + start - The first point at this height 4803 - end - One beyond the last point at this height 4804 4805 Notes: 4806 Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4807 points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4808 stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4809 4810 Level: developer 4811 4812 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight() 4813 @*/ 4814 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4815 { 4816 DMLabel label; 4817 PetscInt depth, pStart, pEnd; 4818 PetscErrorCode ierr; 4819 4820 PetscFunctionBegin; 4821 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4822 if (start) {PetscValidPointer(start, 3); *start = 0;} 4823 if (end) {PetscValidPointer(end, 4); *end = 0;} 4824 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4825 if (pStart == pEnd) PetscFunctionReturn(0); 4826 if (stratumValue < 0) { 4827 if (start) *start = pStart; 4828 if (end) *end = pEnd; 4829 PetscFunctionReturn(0); 4830 } 4831 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4832 PetscCheckFalse(!label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4833 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 4834 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 4835 PetscFunctionReturn(0); 4836 } 4837 4838 /*@ 4839 DMPlexGetPointDepth - Get the depth of a given point 4840 4841 Not Collective 4842 4843 Input Parameters: 4844 + dm - The DMPlex object 4845 - point - The point 4846 4847 Output Parameter: 4848 . depth - The depth of the point 4849 4850 Level: intermediate 4851 4852 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight() 4853 @*/ 4854 PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4855 { 4856 PetscErrorCode ierr; 4857 4858 PetscFunctionBegin; 4859 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4860 PetscValidIntPointer(depth, 3); 4861 ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr); 4862 PetscFunctionReturn(0); 4863 } 4864 4865 /*@ 4866 DMPlexGetPointHeight - Get the height of a given point 4867 4868 Not Collective 4869 4870 Input Parameters: 4871 + dm - The DMPlex object 4872 - point - The point 4873 4874 Output Parameter: 4875 . height - The height of the point 4876 4877 Level: intermediate 4878 4879 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth() 4880 @*/ 4881 PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 4882 { 4883 PetscInt n, pDepth; 4884 PetscErrorCode ierr; 4885 4886 PetscFunctionBegin; 4887 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4888 PetscValidIntPointer(height, 3); 4889 ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr); 4890 ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr); 4891 *height = n - 1 - pDepth; /* DAG depth is n-1 */ 4892 PetscFunctionReturn(0); 4893 } 4894 4895 /*@ 4896 DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4897 4898 Not Collective 4899 4900 Input Parameter: 4901 . dm - The DMPlex object 4902 4903 Output Parameter: 4904 . celltypeLabel - The DMLabel recording cell polytope type 4905 4906 Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4907 DMCreateLabel(dm, "celltype") beforehand. 4908 4909 Level: developer 4910 4911 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel() 4912 @*/ 4913 PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4914 { 4915 PetscErrorCode ierr; 4916 4917 PetscFunctionBegin; 4918 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4919 PetscValidPointer(celltypeLabel, 2); 4920 if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);} 4921 *celltypeLabel = dm->celltypeLabel; 4922 PetscFunctionReturn(0); 4923 } 4924 4925 /*@ 4926 DMPlexGetCellType - Get the polytope type of a given cell 4927 4928 Not Collective 4929 4930 Input Parameters: 4931 + dm - The DMPlex object 4932 - cell - The cell 4933 4934 Output Parameter: 4935 . celltype - The polytope type of the cell 4936 4937 Level: intermediate 4938 4939 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth() 4940 @*/ 4941 PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4942 { 4943 DMLabel label; 4944 PetscInt ct; 4945 PetscErrorCode ierr; 4946 4947 PetscFunctionBegin; 4948 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4949 PetscValidPointer(celltype, 3); 4950 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4951 ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr); 4952 PetscCheckFalse(ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell); 4953 *celltype = (DMPolytopeType) ct; 4954 PetscFunctionReturn(0); 4955 } 4956 4957 /*@ 4958 DMPlexSetCellType - Set the polytope type of a given cell 4959 4960 Not Collective 4961 4962 Input Parameters: 4963 + dm - The DMPlex object 4964 . cell - The cell 4965 - celltype - The polytope type of the cell 4966 4967 Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 4968 is executed. This function will override the computed type. However, if automatic classification will not succeed 4969 and a user wants to manually specify all types, the classification must be disabled by calling 4970 DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 4971 4972 Level: advanced 4973 4974 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel() 4975 @*/ 4976 PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 4977 { 4978 DMLabel label; 4979 PetscErrorCode ierr; 4980 4981 PetscFunctionBegin; 4982 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4983 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4984 ierr = DMLabelSetValue(label, cell, celltype);CHKERRQ(ierr); 4985 PetscFunctionReturn(0); 4986 } 4987 4988 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 4989 { 4990 PetscSection section, s; 4991 Mat m; 4992 PetscInt maxHeight; 4993 PetscErrorCode ierr; 4994 4995 PetscFunctionBegin; 4996 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 4997 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 4998 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 4999 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 5000 ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr); 5001 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5002 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 5003 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 5004 ierr = DMSetDefaultConstraints(*cdm, s, m, NULL);CHKERRQ(ierr); 5005 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 5006 ierr = MatDestroy(&m);CHKERRQ(ierr); 5007 5008 ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr); 5009 ierr = DMCreateDS(*cdm);CHKERRQ(ierr); 5010 PetscFunctionReturn(0); 5011 } 5012 5013 PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5014 { 5015 Vec coordsLocal; 5016 DM coordsDM; 5017 PetscErrorCode ierr; 5018 5019 PetscFunctionBegin; 5020 *field = NULL; 5021 ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr); 5022 ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr); 5023 if (coordsLocal && coordsDM) { 5024 ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr); 5025 } 5026 PetscFunctionReturn(0); 5027 } 5028 5029 /*@C 5030 DMPlexGetConeSection - Return a section which describes the layout of cone data 5031 5032 Not Collective 5033 5034 Input Parameters: 5035 . dm - The DMPlex object 5036 5037 Output Parameter: 5038 . section - The PetscSection object 5039 5040 Level: developer 5041 5042 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 5043 @*/ 5044 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5045 { 5046 DM_Plex *mesh = (DM_Plex*) dm->data; 5047 5048 PetscFunctionBegin; 5049 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5050 if (section) *section = mesh->coneSection; 5051 PetscFunctionReturn(0); 5052 } 5053 5054 /*@C 5055 DMPlexGetSupportSection - Return a section which describes the layout of support data 5056 5057 Not Collective 5058 5059 Input Parameters: 5060 . dm - The DMPlex object 5061 5062 Output Parameter: 5063 . section - The PetscSection object 5064 5065 Level: developer 5066 5067 .seealso: DMPlexGetConeSection() 5068 @*/ 5069 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5070 { 5071 DM_Plex *mesh = (DM_Plex*) dm->data; 5072 5073 PetscFunctionBegin; 5074 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5075 if (section) *section = mesh->supportSection; 5076 PetscFunctionReturn(0); 5077 } 5078 5079 /*@C 5080 DMPlexGetCones - Return cone data 5081 5082 Not Collective 5083 5084 Input Parameters: 5085 . dm - The DMPlex object 5086 5087 Output Parameter: 5088 . cones - The cone for each point 5089 5090 Level: developer 5091 5092 .seealso: DMPlexGetConeSection() 5093 @*/ 5094 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5095 { 5096 DM_Plex *mesh = (DM_Plex*) dm->data; 5097 5098 PetscFunctionBegin; 5099 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5100 if (cones) *cones = mesh->cones; 5101 PetscFunctionReturn(0); 5102 } 5103 5104 /*@C 5105 DMPlexGetConeOrientations - Return cone orientation data 5106 5107 Not Collective 5108 5109 Input Parameters: 5110 . dm - The DMPlex object 5111 5112 Output Parameter: 5113 . coneOrientations - The array of cone orientations for all points 5114 5115 Level: developer 5116 5117 Notes: 5118 The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation(). 5119 5120 The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation(). 5121 5122 .seealso: DMPlexGetConeSection(), DMPlexGetConeOrientation() 5123 @*/ 5124 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5125 { 5126 DM_Plex *mesh = (DM_Plex*) dm->data; 5127 5128 PetscFunctionBegin; 5129 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5130 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 5131 PetscFunctionReturn(0); 5132 } 5133 5134 /******************************** FEM Support **********************************/ 5135 5136 /* 5137 Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 5138 representing a line in the section. 5139 */ 5140 static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 5141 { 5142 PetscErrorCode ierr; 5143 5144 PetscFunctionBeginHot; 5145 ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr); 5146 if (line < 0) { 5147 *k = 0; 5148 *Nc = 0; 5149 } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 5150 *k = 1; 5151 } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 5152 /* An order k SEM disc has k-1 dofs on an edge */ 5153 ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr); 5154 *k = *k / *Nc + 1; 5155 } 5156 PetscFunctionReturn(0); 5157 } 5158 5159 /*@ 5160 5161 DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5162 lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 5163 section provided (or the section of the DM). 5164 5165 Input Parameters: 5166 + dm - The DM 5167 . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 5168 - section - The PetscSection to reorder, or NULL for the default section 5169 5170 Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5171 degree of the basis. 5172 5173 Example: 5174 A typical interpolated single-quad mesh might order points as 5175 .vb 5176 [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5177 5178 v4 -- e6 -- v3 5179 | | 5180 e7 c0 e8 5181 | | 5182 v1 -- e5 -- v2 5183 .ve 5184 5185 (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5186 dofs in the order of points, e.g., 5187 .vb 5188 c0 -> [0,1,2,3] 5189 v1 -> [4] 5190 ... 5191 e5 -> [8, 9] 5192 .ve 5193 5194 which corresponds to the dofs 5195 .vb 5196 6 10 11 7 5197 13 2 3 15 5198 12 0 1 14 5199 4 8 9 5 5200 .ve 5201 5202 The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5203 .vb 5204 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5205 .ve 5206 5207 After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5208 .vb 5209 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5210 .ve 5211 5212 Level: developer 5213 5214 .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection() 5215 @*/ 5216 PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5217 { 5218 DMLabel label; 5219 PetscInt dim, depth = -1, eStart = -1, Nf; 5220 PetscBool vertexchart; 5221 PetscErrorCode ierr; 5222 5223 PetscFunctionBegin; 5224 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5225 if (dim < 1) PetscFunctionReturn(0); 5226 if (point < 0) { 5227 PetscInt sStart,sEnd; 5228 5229 ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr); 5230 point = sEnd-sStart ? sStart : point; 5231 } 5232 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 5233 if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); } 5234 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5235 if (depth == 1) {eStart = point;} 5236 else if (depth == dim) { 5237 const PetscInt *cone; 5238 5239 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5240 if (dim == 2) eStart = cone[0]; 5241 else if (dim == 3) { 5242 const PetscInt *cone2; 5243 ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 5244 eStart = cone2[0]; 5245 } 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); 5246 } 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); 5247 { /* Determine whether the chart covers all points or just vertices. */ 5248 PetscInt pStart,pEnd,cStart,cEnd; 5249 ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr); 5250 ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr); 5251 if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Only vertices are in the chart */ 5252 else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */ 5253 else vertexchart = PETSC_TRUE; /* Some interpolated points are not in chart; assume dofs only at cells and vertices */ 5254 } 5255 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5256 for (PetscInt d=1; d<=dim; d++) { 5257 PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5258 PetscInt *perm; 5259 5260 for (f = 0; f < Nf; ++f) { 5261 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5262 size += PetscPowInt(k+1, d)*Nc; 5263 } 5264 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 5265 for (f = 0; f < Nf; ++f) { 5266 switch (d) { 5267 case 1: 5268 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5269 /* 5270 Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5271 We want [ vtx0; edge of length k-1; vtx1 ] 5272 */ 5273 for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5274 for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5275 for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5276 foffset = offset; 5277 break; 5278 case 2: 5279 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 5280 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5281 /* The SEM order is 5282 5283 v_lb, {e_b}, v_rb, 5284 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 5285 v_lt, reverse {e_t}, v_rt 5286 */ 5287 { 5288 const PetscInt of = 0; 5289 const PetscInt oeb = of + PetscSqr(k-1); 5290 const PetscInt oer = oeb + (k-1); 5291 const PetscInt oet = oer + (k-1); 5292 const PetscInt oel = oet + (k-1); 5293 const PetscInt ovlb = oel + (k-1); 5294 const PetscInt ovrb = ovlb + 1; 5295 const PetscInt ovrt = ovrb + 1; 5296 const PetscInt ovlt = ovrt + 1; 5297 PetscInt o; 5298 5299 /* bottom */ 5300 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 5301 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5302 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 5303 /* middle */ 5304 for (i = 0; i < k-1; ++i) { 5305 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 5306 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; 5307 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 5308 } 5309 /* top */ 5310 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 5311 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5312 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 5313 foffset = offset; 5314 } 5315 break; 5316 case 3: 5317 /* The original hex closure is 5318 5319 {c, 5320 f_b, f_t, f_f, f_b, f_r, f_l, 5321 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 5322 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 5323 */ 5324 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5325 /* The SEM order is 5326 Bottom Slice 5327 v_blf, {e^{(k-1)-n}_bf}, v_brf, 5328 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 5329 v_blb, {e_bb}, v_brb, 5330 5331 Middle Slice (j) 5332 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 5333 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 5334 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 5335 5336 Top Slice 5337 v_tlf, {e_tf}, v_trf, 5338 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 5339 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 5340 */ 5341 { 5342 const PetscInt oc = 0; 5343 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 5344 const PetscInt oft = ofb + PetscSqr(k-1); 5345 const PetscInt off = oft + PetscSqr(k-1); 5346 const PetscInt ofk = off + PetscSqr(k-1); 5347 const PetscInt ofr = ofk + PetscSqr(k-1); 5348 const PetscInt ofl = ofr + PetscSqr(k-1); 5349 const PetscInt oebl = ofl + PetscSqr(k-1); 5350 const PetscInt oebb = oebl + (k-1); 5351 const PetscInt oebr = oebb + (k-1); 5352 const PetscInt oebf = oebr + (k-1); 5353 const PetscInt oetf = oebf + (k-1); 5354 const PetscInt oetr = oetf + (k-1); 5355 const PetscInt oetb = oetr + (k-1); 5356 const PetscInt oetl = oetb + (k-1); 5357 const PetscInt oerf = oetl + (k-1); 5358 const PetscInt oelf = oerf + (k-1); 5359 const PetscInt oelb = oelf + (k-1); 5360 const PetscInt oerb = oelb + (k-1); 5361 const PetscInt ovblf = oerb + (k-1); 5362 const PetscInt ovblb = ovblf + 1; 5363 const PetscInt ovbrb = ovblb + 1; 5364 const PetscInt ovbrf = ovbrb + 1; 5365 const PetscInt ovtlf = ovbrf + 1; 5366 const PetscInt ovtrf = ovtlf + 1; 5367 const PetscInt ovtrb = ovtrf + 1; 5368 const PetscInt ovtlb = ovtrb + 1; 5369 PetscInt o, n; 5370 5371 /* Bottom Slice */ 5372 /* bottom */ 5373 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 5374 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5375 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 5376 /* middle */ 5377 for (i = 0; i < k-1; ++i) { 5378 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5379 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;} 5380 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 5381 } 5382 /* top */ 5383 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 5384 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5385 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 5386 5387 /* Middle Slice */ 5388 for (j = 0; j < k-1; ++j) { 5389 /* bottom */ 5390 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 5391 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; 5392 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 5393 /* middle */ 5394 for (i = 0; i < k-1; ++i) { 5395 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 5396 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; 5397 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 5398 } 5399 /* top */ 5400 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 5401 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; 5402 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 5403 } 5404 5405 /* Top Slice */ 5406 /* bottom */ 5407 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 5408 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5409 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 5410 /* middle */ 5411 for (i = 0; i < k-1; ++i) { 5412 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 5413 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 5414 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 5415 } 5416 /* top */ 5417 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 5418 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5419 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 5420 5421 foffset = offset; 5422 } 5423 break; 5424 default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d); 5425 } 5426 } 5427 PetscCheckFalse(offset != size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 5428 /* Check permutation */ 5429 { 5430 PetscInt *check; 5431 5432 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 5433 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]);} 5434 for (i = 0; i < size; ++i) check[perm[i]] = i; 5435 for (i = 0; i < size; ++i) {PetscCheckFalse(check[i] < 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 5436 ierr = PetscFree(check);CHKERRQ(ierr); 5437 } 5438 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 5439 if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 5440 PetscInt *loc_perm; 5441 ierr = PetscMalloc1(size*2, &loc_perm);CHKERRQ(ierr); 5442 for (PetscInt i=0; i<size; i++) { 5443 loc_perm[i] = perm[i]; 5444 loc_perm[size+i] = size + perm[i]; 5445 } 5446 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm);CHKERRQ(ierr); 5447 } 5448 } 5449 PetscFunctionReturn(0); 5450 } 5451 5452 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5453 { 5454 PetscDS prob; 5455 PetscInt depth, Nf, h; 5456 DMLabel label; 5457 PetscErrorCode ierr; 5458 5459 PetscFunctionBeginHot; 5460 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 5461 Nf = prob->Nf; 5462 label = dm->depthLabel; 5463 *dspace = NULL; 5464 if (field < Nf) { 5465 PetscObject disc = prob->disc[field]; 5466 5467 if (disc->classid == PETSCFE_CLASSID) { 5468 PetscDualSpace dsp; 5469 5470 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 5471 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 5472 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 5473 h = depth - 1 - h; 5474 if (h) { 5475 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 5476 } else { 5477 *dspace = dsp; 5478 } 5479 } 5480 } 5481 PetscFunctionReturn(0); 5482 } 5483 5484 static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5485 { 5486 PetscScalar *array, *vArray; 5487 const PetscInt *cone, *coneO; 5488 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5489 PetscErrorCode ierr; 5490 5491 PetscFunctionBeginHot; 5492 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5493 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5494 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5495 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5496 if (!values || !*values) { 5497 if ((point >= pStart) && (point < pEnd)) { 5498 PetscInt dof; 5499 5500 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5501 size += dof; 5502 } 5503 for (p = 0; p < numPoints; ++p) { 5504 const PetscInt cp = cone[p]; 5505 PetscInt dof; 5506 5507 if ((cp < pStart) || (cp >= pEnd)) continue; 5508 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5509 size += dof; 5510 } 5511 if (!values) { 5512 if (csize) *csize = size; 5513 PetscFunctionReturn(0); 5514 } 5515 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 5516 } else { 5517 array = *values; 5518 } 5519 size = 0; 5520 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 5521 if ((point >= pStart) && (point < pEnd)) { 5522 PetscInt dof, off, d; 5523 PetscScalar *varr; 5524 5525 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5526 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5527 varr = &vArray[off]; 5528 for (d = 0; d < dof; ++d, ++offset) { 5529 array[offset] = varr[d]; 5530 } 5531 size += dof; 5532 } 5533 for (p = 0; p < numPoints; ++p) { 5534 const PetscInt cp = cone[p]; 5535 PetscInt o = coneO[p]; 5536 PetscInt dof, off, d; 5537 PetscScalar *varr; 5538 5539 if ((cp < pStart) || (cp >= pEnd)) continue; 5540 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5541 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 5542 varr = &vArray[off]; 5543 if (o >= 0) { 5544 for (d = 0; d < dof; ++d, ++offset) { 5545 array[offset] = varr[d]; 5546 } 5547 } else { 5548 for (d = dof-1; d >= 0; --d, ++offset) { 5549 array[offset] = varr[d]; 5550 } 5551 } 5552 size += dof; 5553 } 5554 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 5555 if (!*values) { 5556 if (csize) *csize = size; 5557 *values = array; 5558 } else { 5559 PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5560 *csize = size; 5561 } 5562 PetscFunctionReturn(0); 5563 } 5564 5565 /* Compress out points not in the section */ 5566 static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 5567 { 5568 const PetscInt np = *numPoints; 5569 PetscInt pStart, pEnd, p, q; 5570 PetscErrorCode ierr; 5571 5572 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5573 for (p = 0, q = 0; p < np; ++p) { 5574 const PetscInt r = points[p*2]; 5575 if ((r >= pStart) && (r < pEnd)) { 5576 points[q*2] = r; 5577 points[q*2+1] = points[p*2+1]; 5578 ++q; 5579 } 5580 } 5581 *numPoints = q; 5582 return 0; 5583 } 5584 5585 /* Compressed closure does not apply closure permutation */ 5586 PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5587 { 5588 const PetscInt *cla = NULL; 5589 PetscInt np, *pts = NULL; 5590 PetscErrorCode ierr; 5591 5592 PetscFunctionBeginHot; 5593 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 5594 if (*clPoints) { 5595 PetscInt dof, off; 5596 5597 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 5598 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 5599 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 5600 np = dof/2; 5601 pts = (PetscInt *) &cla[off]; 5602 } else { 5603 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 5604 ierr = CompressPoints_Private(section, &np, pts);CHKERRQ(ierr); 5605 } 5606 *numPoints = np; 5607 *points = pts; 5608 *clp = cla; 5609 PetscFunctionReturn(0); 5610 } 5611 5612 PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5613 { 5614 PetscErrorCode ierr; 5615 5616 PetscFunctionBeginHot; 5617 if (!*clPoints) { 5618 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 5619 } else { 5620 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 5621 } 5622 *numPoints = 0; 5623 *points = NULL; 5624 *clSec = NULL; 5625 *clPoints = NULL; 5626 *clp = NULL; 5627 PetscFunctionReturn(0); 5628 } 5629 5630 static inline PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 5631 { 5632 PetscInt offset = 0, p; 5633 const PetscInt **perms = NULL; 5634 const PetscScalar **flips = NULL; 5635 PetscErrorCode ierr; 5636 5637 PetscFunctionBeginHot; 5638 *size = 0; 5639 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5640 for (p = 0; p < numPoints; p++) { 5641 const PetscInt point = points[2*p]; 5642 const PetscInt *perm = perms ? perms[p] : NULL; 5643 const PetscScalar *flip = flips ? flips[p] : NULL; 5644 PetscInt dof, off, d; 5645 const PetscScalar *varr; 5646 5647 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5648 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5649 varr = &vArray[off]; 5650 if (clperm) { 5651 if (perm) { 5652 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 5653 } else { 5654 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 5655 } 5656 if (flip) { 5657 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 5658 } 5659 } else { 5660 if (perm) { 5661 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 5662 } else { 5663 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 5664 } 5665 if (flip) { 5666 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 5667 } 5668 } 5669 offset += dof; 5670 } 5671 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5672 *size = offset; 5673 PetscFunctionReturn(0); 5674 } 5675 5676 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[]) 5677 { 5678 PetscInt offset = 0, f; 5679 PetscErrorCode ierr; 5680 5681 PetscFunctionBeginHot; 5682 *size = 0; 5683 for (f = 0; f < numFields; ++f) { 5684 PetscInt p; 5685 const PetscInt **perms = NULL; 5686 const PetscScalar **flips = NULL; 5687 5688 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5689 for (p = 0; p < numPoints; p++) { 5690 const PetscInt point = points[2*p]; 5691 PetscInt fdof, foff, b; 5692 const PetscScalar *varr; 5693 const PetscInt *perm = perms ? perms[p] : NULL; 5694 const PetscScalar *flip = flips ? flips[p] : NULL; 5695 5696 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5697 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5698 varr = &vArray[foff]; 5699 if (clperm) { 5700 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 5701 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 5702 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 5703 } else { 5704 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 5705 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 5706 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 5707 } 5708 offset += fdof; 5709 } 5710 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5711 } 5712 *size = offset; 5713 PetscFunctionReturn(0); 5714 } 5715 5716 /*@C 5717 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5718 5719 Not collective 5720 5721 Input Parameters: 5722 + dm - The DM 5723 . section - The section describing the layout in v, or NULL to use the default section 5724 . v - The local vector 5725 - point - The point in the DM 5726 5727 Input/Output Parameters: 5728 + csize - The size of the input values array, or NULL; on output the number of values in the closure 5729 - values - An array to use for the values, or NULL to have it allocated automatically; 5730 if the user provided NULL, it is a borrowed array and should not be freed 5731 5732 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 5733 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 5734 $ assembly function, and a user may already have allocated storage for this operation. 5735 $ 5736 $ A typical use could be 5737 $ 5738 $ values = NULL; 5739 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5740 $ for (cl = 0; cl < clSize; ++cl) { 5741 $ <Compute on closure> 5742 $ } 5743 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5744 $ 5745 $ or 5746 $ 5747 $ PetscMalloc1(clMaxSize, &values); 5748 $ for (p = pStart; p < pEnd; ++p) { 5749 $ clSize = clMaxSize; 5750 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5751 $ for (cl = 0; cl < clSize; ++cl) { 5752 $ <Compute on closure> 5753 $ } 5754 $ } 5755 $ PetscFree(values); 5756 5757 Fortran Notes: 5758 Since it returns an array, this routine is only available in Fortran 90, and you must 5759 include petsc.h90 in your code. 5760 5761 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5762 5763 Level: intermediate 5764 5765 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5766 @*/ 5767 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5768 { 5769 PetscSection clSection; 5770 IS clPoints; 5771 PetscInt *points = NULL; 5772 const PetscInt *clp, *perm; 5773 PetscInt depth, numFields, numPoints, asize; 5774 PetscErrorCode ierr; 5775 5776 PetscFunctionBeginHot; 5777 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5778 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5779 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5780 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5781 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5782 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5783 if (depth == 1 && numFields < 2) { 5784 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5785 PetscFunctionReturn(0); 5786 } 5787 /* Get points */ 5788 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5789 /* Get sizes */ 5790 asize = 0; 5791 for (PetscInt p = 0; p < numPoints*2; p += 2) { 5792 PetscInt dof; 5793 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5794 asize += dof; 5795 } 5796 if (values) { 5797 const PetscScalar *vArray; 5798 PetscInt size; 5799 5800 if (*values) { 5801 PetscCheckFalse(*csize < asize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %D not sufficient to hold closure size %D", *csize, asize); 5802 } else {ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, values);CHKERRQ(ierr);} 5803 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm);CHKERRQ(ierr); 5804 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5805 /* Get values */ 5806 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values);CHKERRQ(ierr);} 5807 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values);CHKERRQ(ierr);} 5808 PetscCheckFalse(asize != size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size); 5809 /* Cleanup array */ 5810 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5811 } 5812 if (csize) *csize = asize; 5813 /* Cleanup points */ 5814 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5815 PetscFunctionReturn(0); 5816 } 5817 5818 PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5819 { 5820 DMLabel depthLabel; 5821 PetscSection clSection; 5822 IS clPoints; 5823 PetscScalar *array; 5824 const PetscScalar *vArray; 5825 PetscInt *points = NULL; 5826 const PetscInt *clp, *perm = NULL; 5827 PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5828 PetscErrorCode ierr; 5829 5830 PetscFunctionBeginHot; 5831 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5832 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5833 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5834 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5835 ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr); 5836 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 5837 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5838 if (mdepth == 1 && numFields < 2) { 5839 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5840 PetscFunctionReturn(0); 5841 } 5842 /* Get points */ 5843 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5844 for (clsize=0,p=0; p<Np; p++) { 5845 PetscInt dof; 5846 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 5847 clsize += dof; 5848 } 5849 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm);CHKERRQ(ierr); 5850 /* Filter points */ 5851 for (p = 0; p < numPoints*2; p += 2) { 5852 PetscInt dep; 5853 5854 ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr); 5855 if (dep != depth) continue; 5856 points[Np*2+0] = points[p]; 5857 points[Np*2+1] = points[p+1]; 5858 ++Np; 5859 } 5860 /* Get array */ 5861 if (!values || !*values) { 5862 PetscInt asize = 0, dof; 5863 5864 for (p = 0; p < Np*2; p += 2) { 5865 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5866 asize += dof; 5867 } 5868 if (!values) { 5869 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5870 if (csize) *csize = asize; 5871 PetscFunctionReturn(0); 5872 } 5873 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 5874 } else { 5875 array = *values; 5876 } 5877 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5878 /* Get values */ 5879 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 5880 else {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);} 5881 /* Cleanup points */ 5882 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5883 /* Cleanup array */ 5884 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5885 if (!*values) { 5886 if (csize) *csize = size; 5887 *values = array; 5888 } else { 5889 PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5890 *csize = size; 5891 } 5892 PetscFunctionReturn(0); 5893 } 5894 5895 /*@C 5896 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5897 5898 Not collective 5899 5900 Input Parameters: 5901 + dm - The DM 5902 . section - The section describing the layout in v, or NULL to use the default section 5903 . v - The local vector 5904 . point - The point in the DM 5905 . csize - The number of values in the closure, or NULL 5906 - values - The array of values, which is a borrowed array and should not be freed 5907 5908 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 5909 5910 Fortran Notes: 5911 Since it returns an array, this routine is only available in Fortran 90, and you must 5912 include petsc.h90 in your code. 5913 5914 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5915 5916 Level: intermediate 5917 5918 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5919 @*/ 5920 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5921 { 5922 PetscInt size = 0; 5923 PetscErrorCode ierr; 5924 5925 PetscFunctionBegin; 5926 /* Should work without recalculating size */ 5927 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 5928 *values = NULL; 5929 PetscFunctionReturn(0); 5930 } 5931 5932 static inline void add (PetscScalar *x, PetscScalar y) {*x += y;} 5933 static inline void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5934 5935 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[]) 5936 { 5937 PetscInt cdof; /* The number of constraints on this point */ 5938 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5939 PetscScalar *a; 5940 PetscInt off, cind = 0, k; 5941 PetscErrorCode ierr; 5942 5943 PetscFunctionBegin; 5944 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5945 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5946 a = &array[off]; 5947 if (!cdof || setBC) { 5948 if (clperm) { 5949 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 5950 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5951 } else { 5952 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 5953 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5954 } 5955 } else { 5956 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5957 if (clperm) { 5958 if (perm) {for (k = 0; k < dof; ++k) { 5959 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5960 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5961 } 5962 } else { 5963 for (k = 0; k < dof; ++k) { 5964 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5965 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5966 } 5967 } 5968 } else { 5969 if (perm) { 5970 for (k = 0; k < dof; ++k) { 5971 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5972 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5973 } 5974 } else { 5975 for (k = 0; k < dof; ++k) { 5976 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5977 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5978 } 5979 } 5980 } 5981 } 5982 PetscFunctionReturn(0); 5983 } 5984 5985 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[]) 5986 { 5987 PetscInt cdof; /* The number of constraints on this point */ 5988 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5989 PetscScalar *a; 5990 PetscInt off, cind = 0, k; 5991 PetscErrorCode ierr; 5992 5993 PetscFunctionBegin; 5994 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5995 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5996 a = &array[off]; 5997 if (cdof) { 5998 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5999 if (clperm) { 6000 if (perm) { 6001 for (k = 0; k < dof; ++k) { 6002 if ((cind < cdof) && (k == cdofs[cind])) { 6003 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6004 cind++; 6005 } 6006 } 6007 } else { 6008 for (k = 0; k < dof; ++k) { 6009 if ((cind < cdof) && (k == cdofs[cind])) { 6010 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 6011 cind++; 6012 } 6013 } 6014 } 6015 } else { 6016 if (perm) { 6017 for (k = 0; k < dof; ++k) { 6018 if ((cind < cdof) && (k == cdofs[cind])) { 6019 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 6020 cind++; 6021 } 6022 } 6023 } else { 6024 for (k = 0; k < dof; ++k) { 6025 if ((cind < cdof) && (k == cdofs[cind])) { 6026 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 6027 cind++; 6028 } 6029 } 6030 } 6031 } 6032 } 6033 PetscFunctionReturn(0); 6034 } 6035 6036 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[]) 6037 { 6038 PetscScalar *a; 6039 PetscInt fdof, foff, fcdof, foffset = *offset; 6040 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6041 PetscInt cind = 0, b; 6042 PetscErrorCode ierr; 6043 6044 PetscFunctionBegin; 6045 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6046 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6047 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 6048 a = &array[foff]; 6049 if (!fcdof || setBC) { 6050 if (clperm) { 6051 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 6052 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 6053 } else { 6054 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 6055 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 6056 } 6057 } else { 6058 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6059 if (clperm) { 6060 if (perm) { 6061 for (b = 0; b < fdof; b++) { 6062 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6063 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6064 } 6065 } else { 6066 for (b = 0; b < fdof; b++) { 6067 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6068 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6069 } 6070 } 6071 } else { 6072 if (perm) { 6073 for (b = 0; b < fdof; b++) { 6074 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6075 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6076 } 6077 } else { 6078 for (b = 0; b < fdof; b++) { 6079 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6080 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6081 } 6082 } 6083 } 6084 } 6085 *offset += fdof; 6086 PetscFunctionReturn(0); 6087 } 6088 6089 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[]) 6090 { 6091 PetscScalar *a; 6092 PetscInt fdof, foff, fcdof, foffset = *offset; 6093 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6094 PetscInt Nc, cind = 0, ncind = 0, b; 6095 PetscBool ncSet, fcSet; 6096 PetscErrorCode ierr; 6097 6098 PetscFunctionBegin; 6099 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 6100 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6101 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6102 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 6103 a = &array[foff]; 6104 if (fcdof) { 6105 /* We just override fcdof and fcdofs with Ncc and comps */ 6106 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6107 if (clperm) { 6108 if (perm) { 6109 if (comps) { 6110 for (b = 0; b < fdof; b++) { 6111 ncSet = fcSet = PETSC_FALSE; 6112 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6113 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6114 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 6115 } 6116 } else { 6117 for (b = 0; b < fdof; b++) { 6118 if ((cind < fcdof) && (b == fcdofs[cind])) { 6119 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6120 ++cind; 6121 } 6122 } 6123 } 6124 } else { 6125 if (comps) { 6126 for (b = 0; b < fdof; b++) { 6127 ncSet = fcSet = PETSC_FALSE; 6128 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6129 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6130 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 6131 } 6132 } else { 6133 for (b = 0; b < fdof; b++) { 6134 if ((cind < fcdof) && (b == fcdofs[cind])) { 6135 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6136 ++cind; 6137 } 6138 } 6139 } 6140 } 6141 } else { 6142 if (perm) { 6143 if (comps) { 6144 for (b = 0; b < fdof; b++) { 6145 ncSet = fcSet = PETSC_FALSE; 6146 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6147 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6148 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 6149 } 6150 } else { 6151 for (b = 0; b < fdof; b++) { 6152 if ((cind < fcdof) && (b == fcdofs[cind])) { 6153 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6154 ++cind; 6155 } 6156 } 6157 } 6158 } else { 6159 if (comps) { 6160 for (b = 0; b < fdof; b++) { 6161 ncSet = fcSet = PETSC_FALSE; 6162 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6163 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6164 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 6165 } 6166 } else { 6167 for (b = 0; b < fdof; b++) { 6168 if ((cind < fcdof) && (b == fcdofs[cind])) { 6169 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6170 ++cind; 6171 } 6172 } 6173 } 6174 } 6175 } 6176 } 6177 *offset += fdof; 6178 PetscFunctionReturn(0); 6179 } 6180 6181 static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6182 { 6183 PetscScalar *array; 6184 const PetscInt *cone, *coneO; 6185 PetscInt pStart, pEnd, p, numPoints, off, dof; 6186 PetscErrorCode ierr; 6187 6188 PetscFunctionBeginHot; 6189 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6190 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 6191 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 6192 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 6193 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6194 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6195 const PetscInt cp = !p ? point : cone[p-1]; 6196 const PetscInt o = !p ? 0 : coneO[p-1]; 6197 6198 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 6199 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 6200 /* ADD_VALUES */ 6201 { 6202 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6203 PetscScalar *a; 6204 PetscInt cdof, coff, cind = 0, k; 6205 6206 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 6207 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 6208 a = &array[coff]; 6209 if (!cdof) { 6210 if (o >= 0) { 6211 for (k = 0; k < dof; ++k) { 6212 a[k] += values[off+k]; 6213 } 6214 } else { 6215 for (k = 0; k < dof; ++k) { 6216 a[k] += values[off+dof-k-1]; 6217 } 6218 } 6219 } else { 6220 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 6221 if (o >= 0) { 6222 for (k = 0; k < dof; ++k) { 6223 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6224 a[k] += values[off+k]; 6225 } 6226 } else { 6227 for (k = 0; k < dof; ++k) { 6228 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6229 a[k] += values[off+dof-k-1]; 6230 } 6231 } 6232 } 6233 } 6234 } 6235 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6236 PetscFunctionReturn(0); 6237 } 6238 6239 /*@C 6240 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6241 6242 Not collective 6243 6244 Input Parameters: 6245 + dm - The DM 6246 . section - The section describing the layout in v, or NULL to use the default section 6247 . v - The local vector 6248 . point - The point in the DM 6249 . values - The array of values 6250 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 6251 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 6252 6253 Fortran Notes: 6254 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6255 6256 Level: intermediate 6257 6258 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6259 @*/ 6260 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6261 { 6262 PetscSection clSection; 6263 IS clPoints; 6264 PetscScalar *array; 6265 PetscInt *points = NULL; 6266 const PetscInt *clp, *clperm = NULL; 6267 PetscInt depth, numFields, numPoints, p, clsize; 6268 PetscErrorCode ierr; 6269 6270 PetscFunctionBeginHot; 6271 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6272 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6273 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6274 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6275 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6276 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6277 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 6278 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 6279 PetscFunctionReturn(0); 6280 } 6281 /* Get points */ 6282 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6283 for (clsize=0,p=0; p<numPoints; p++) { 6284 PetscInt dof; 6285 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 6286 clsize += dof; 6287 } 6288 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 6289 /* Get array */ 6290 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6291 /* Get values */ 6292 if (numFields > 0) { 6293 PetscInt offset = 0, f; 6294 for (f = 0; f < numFields; ++f) { 6295 const PetscInt **perms = NULL; 6296 const PetscScalar **flips = NULL; 6297 6298 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6299 switch (mode) { 6300 case INSERT_VALUES: 6301 for (p = 0; p < numPoints; p++) { 6302 const PetscInt point = points[2*p]; 6303 const PetscInt *perm = perms ? perms[p] : NULL; 6304 const PetscScalar *flip = flips ? flips[p] : NULL; 6305 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6306 } break; 6307 case INSERT_ALL_VALUES: 6308 for (p = 0; p < numPoints; p++) { 6309 const PetscInt point = points[2*p]; 6310 const PetscInt *perm = perms ? perms[p] : NULL; 6311 const PetscScalar *flip = flips ? flips[p] : NULL; 6312 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6313 } break; 6314 case INSERT_BC_VALUES: 6315 for (p = 0; p < numPoints; p++) { 6316 const PetscInt point = points[2*p]; 6317 const PetscInt *perm = perms ? perms[p] : NULL; 6318 const PetscScalar *flip = flips ? flips[p] : NULL; 6319 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6320 } break; 6321 case ADD_VALUES: 6322 for (p = 0; p < numPoints; p++) { 6323 const PetscInt point = points[2*p]; 6324 const PetscInt *perm = perms ? perms[p] : NULL; 6325 const PetscScalar *flip = flips ? flips[p] : NULL; 6326 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6327 } break; 6328 case ADD_ALL_VALUES: 6329 for (p = 0; p < numPoints; p++) { 6330 const PetscInt point = points[2*p]; 6331 const PetscInt *perm = perms ? perms[p] : NULL; 6332 const PetscScalar *flip = flips ? flips[p] : NULL; 6333 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6334 } break; 6335 case ADD_BC_VALUES: 6336 for (p = 0; p < numPoints; p++) { 6337 const PetscInt point = points[2*p]; 6338 const PetscInt *perm = perms ? perms[p] : NULL; 6339 const PetscScalar *flip = flips ? flips[p] : NULL; 6340 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6341 } break; 6342 default: 6343 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6344 } 6345 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6346 } 6347 } else { 6348 PetscInt dof, off; 6349 const PetscInt **perms = NULL; 6350 const PetscScalar **flips = NULL; 6351 6352 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6353 switch (mode) { 6354 case INSERT_VALUES: 6355 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6356 const PetscInt point = points[2*p]; 6357 const PetscInt *perm = perms ? perms[p] : NULL; 6358 const PetscScalar *flip = flips ? flips[p] : NULL; 6359 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6360 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6361 } break; 6362 case INSERT_ALL_VALUES: 6363 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6364 const PetscInt point = points[2*p]; 6365 const PetscInt *perm = perms ? perms[p] : NULL; 6366 const PetscScalar *flip = flips ? flips[p] : NULL; 6367 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6368 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6369 } break; 6370 case INSERT_BC_VALUES: 6371 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6372 const PetscInt point = points[2*p]; 6373 const PetscInt *perm = perms ? perms[p] : NULL; 6374 const PetscScalar *flip = flips ? flips[p] : NULL; 6375 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6376 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6377 } break; 6378 case ADD_VALUES: 6379 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6380 const PetscInt point = points[2*p]; 6381 const PetscInt *perm = perms ? perms[p] : NULL; 6382 const PetscScalar *flip = flips ? flips[p] : NULL; 6383 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6384 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6385 } break; 6386 case ADD_ALL_VALUES: 6387 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6388 const PetscInt point = points[2*p]; 6389 const PetscInt *perm = perms ? perms[p] : NULL; 6390 const PetscScalar *flip = flips ? flips[p] : NULL; 6391 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6392 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6393 } break; 6394 case ADD_BC_VALUES: 6395 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6396 const PetscInt point = points[2*p]; 6397 const PetscInt *perm = perms ? perms[p] : NULL; 6398 const PetscScalar *flip = flips ? flips[p] : NULL; 6399 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6400 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6401 } break; 6402 default: 6403 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6404 } 6405 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6406 } 6407 /* Cleanup points */ 6408 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6409 /* Cleanup array */ 6410 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6411 PetscFunctionReturn(0); 6412 } 6413 6414 /* Check whether the given point is in the label. If not, update the offset to skip this point */ 6415 static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 6416 { 6417 PetscFunctionBegin; 6418 if (label) { 6419 PetscInt val, fdof; 6420 PetscErrorCode ierr; 6421 6422 /* There is a problem with this: 6423 Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that 6424 touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell. 6425 Thus I am only going to check val != -1, not val != labelId 6426 */ 6427 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 6428 if (val < 0) { 6429 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6430 *offset += fdof; 6431 PetscFunctionReturn(1); 6432 } 6433 } 6434 PetscFunctionReturn(0); 6435 } 6436 6437 /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 6438 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) 6439 { 6440 PetscSection clSection; 6441 IS clPoints; 6442 PetscScalar *array; 6443 PetscInt *points = NULL; 6444 const PetscInt *clp; 6445 PetscInt numFields, numPoints, p; 6446 PetscInt offset = 0, f; 6447 PetscErrorCode ierr; 6448 6449 PetscFunctionBeginHot; 6450 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6451 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6452 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6453 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6454 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6455 /* Get points */ 6456 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6457 /* Get array */ 6458 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6459 /* Get values */ 6460 for (f = 0; f < numFields; ++f) { 6461 const PetscInt **perms = NULL; 6462 const PetscScalar **flips = NULL; 6463 6464 if (!fieldActive[f]) { 6465 for (p = 0; p < numPoints*2; p += 2) { 6466 PetscInt fdof; 6467 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6468 offset += fdof; 6469 } 6470 continue; 6471 } 6472 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6473 switch (mode) { 6474 case INSERT_VALUES: 6475 for (p = 0; p < numPoints; p++) { 6476 const PetscInt point = points[2*p]; 6477 const PetscInt *perm = perms ? perms[p] : NULL; 6478 const PetscScalar *flip = flips ? flips[p] : NULL; 6479 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6480 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array); 6481 } break; 6482 case INSERT_ALL_VALUES: 6483 for (p = 0; p < numPoints; p++) { 6484 const PetscInt point = points[2*p]; 6485 const PetscInt *perm = perms ? perms[p] : NULL; 6486 const PetscScalar *flip = flips ? flips[p] : NULL; 6487 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6488 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array); 6489 } break; 6490 case INSERT_BC_VALUES: 6491 for (p = 0; p < numPoints; p++) { 6492 const PetscInt point = points[2*p]; 6493 const PetscInt *perm = perms ? perms[p] : NULL; 6494 const PetscScalar *flip = flips ? flips[p] : NULL; 6495 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6496 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array); 6497 } break; 6498 case ADD_VALUES: 6499 for (p = 0; p < numPoints; p++) { 6500 const PetscInt point = points[2*p]; 6501 const PetscInt *perm = perms ? perms[p] : NULL; 6502 const PetscScalar *flip = flips ? flips[p] : NULL; 6503 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6504 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array); 6505 } break; 6506 case ADD_ALL_VALUES: 6507 for (p = 0; p < numPoints; p++) { 6508 const PetscInt point = points[2*p]; 6509 const PetscInt *perm = perms ? perms[p] : NULL; 6510 const PetscScalar *flip = flips ? flips[p] : NULL; 6511 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6512 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array); 6513 } break; 6514 default: 6515 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6516 } 6517 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6518 } 6519 /* Cleanup points */ 6520 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6521 /* Cleanup array */ 6522 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6523 PetscFunctionReturn(0); 6524 } 6525 6526 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6527 { 6528 PetscMPIInt rank; 6529 PetscInt i, j; 6530 PetscErrorCode ierr; 6531 6532 PetscFunctionBegin; 6533 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr); 6534 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 6535 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 6536 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 6537 numCIndices = numCIndices ? numCIndices : numRIndices; 6538 if (!values) PetscFunctionReturn(0); 6539 for (i = 0; i < numRIndices; i++) { 6540 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 6541 for (j = 0; j < numCIndices; j++) { 6542 #if defined(PETSC_USE_COMPLEX) 6543 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 6544 #else 6545 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 6546 #endif 6547 } 6548 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6549 } 6550 PetscFunctionReturn(0); 6551 } 6552 6553 /* 6554 DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 6555 6556 Input Parameters: 6557 + section - The section for this data layout 6558 . islocal - Is the section (and thus indices being requested) local or global? 6559 . point - The point contributing dofs with these indices 6560 . off - The global offset of this point 6561 . loff - The local offset of each field 6562 . setBC - The flag determining whether to include indices of boundary values 6563 . perm - A permutation of the dofs on this point, or NULL 6564 - indperm - A permutation of the entire indices array, or NULL 6565 6566 Output Parameter: 6567 . indices - Indices for dofs on this point 6568 6569 Level: developer 6570 6571 Note: The indices could be local or global, depending on the value of 'off'. 6572 */ 6573 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6574 { 6575 PetscInt dof; /* The number of unknowns on this point */ 6576 PetscInt cdof; /* The number of constraints on this point */ 6577 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6578 PetscInt cind = 0, k; 6579 PetscErrorCode ierr; 6580 6581 PetscFunctionBegin; 6582 PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6583 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6584 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6585 if (!cdof || setBC) { 6586 for (k = 0; k < dof; ++k) { 6587 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6588 const PetscInt ind = indperm ? indperm[preind] : preind; 6589 6590 indices[ind] = off + k; 6591 } 6592 } else { 6593 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6594 for (k = 0; k < dof; ++k) { 6595 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6596 const PetscInt ind = indperm ? indperm[preind] : preind; 6597 6598 if ((cind < cdof) && (k == cdofs[cind])) { 6599 /* Insert check for returning constrained indices */ 6600 indices[ind] = -(off+k+1); 6601 ++cind; 6602 } else { 6603 indices[ind] = off + k - (islocal ? 0 : cind); 6604 } 6605 } 6606 } 6607 *loff += dof; 6608 PetscFunctionReturn(0); 6609 } 6610 6611 /* 6612 DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 6613 6614 Input Parameters: 6615 + section - a section (global or local) 6616 - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 6617 . point - point within section 6618 . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 6619 . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 6620 . setBC - identify constrained (boundary condition) points via involution. 6621 . perms - perms[f][permsoff][:] is a permutation of dofs within each field 6622 . permsoff - offset 6623 - indperm - index permutation 6624 6625 Output Parameter: 6626 . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 6627 . indices - array to hold indices (as defined by section) of each dof associated with point 6628 6629 Notes: 6630 If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 6631 If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 6632 in the local vector. 6633 6634 If section is global and setBC=false, the indices for constrained points are negative (and their value is not 6635 significant). It is invalid to call with a global section and setBC=true. 6636 6637 Developer Note: 6638 The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 6639 in the future, global sections may have fields set, in which case we could pass the global section and obtain the 6640 offset could be obtained from the section instead of passing it explicitly as we do now. 6641 6642 Example: 6643 Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 6644 When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 6645 Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 6646 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. 6647 6648 Level: developer 6649 */ 6650 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[]) 6651 { 6652 PetscInt numFields, foff, f; 6653 PetscErrorCode ierr; 6654 6655 PetscFunctionBegin; 6656 PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6657 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6658 for (f = 0, foff = 0; f < numFields; ++f) { 6659 PetscInt fdof, cfdof; 6660 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6661 PetscInt cind = 0, b; 6662 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6663 6664 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6665 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6666 if (!cfdof || setBC) { 6667 for (b = 0; b < fdof; ++b) { 6668 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6669 const PetscInt ind = indperm ? indperm[preind] : preind; 6670 6671 indices[ind] = off+foff+b; 6672 } 6673 } else { 6674 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6675 for (b = 0; b < fdof; ++b) { 6676 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6677 const PetscInt ind = indperm ? indperm[preind] : preind; 6678 6679 if ((cind < cfdof) && (b == fcdofs[cind])) { 6680 indices[ind] = -(off+foff+b+1); 6681 ++cind; 6682 } else { 6683 indices[ind] = off + foff + b - (islocal ? 0 : cind); 6684 } 6685 } 6686 } 6687 foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6688 foffs[f] += fdof; 6689 } 6690 PetscFunctionReturn(0); 6691 } 6692 6693 /* 6694 This version believes the globalSection offsets for each field, rather than just the point offset 6695 6696 . foffs - The offset into 'indices' for each field, since it is segregated by field 6697 6698 Notes: 6699 The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6700 Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 6701 */ 6702 static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 6703 { 6704 PetscInt numFields, foff, f; 6705 PetscErrorCode ierr; 6706 6707 PetscFunctionBegin; 6708 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6709 for (f = 0; f < numFields; ++f) { 6710 PetscInt fdof, cfdof; 6711 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6712 PetscInt cind = 0, b; 6713 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6714 6715 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6716 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6717 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 6718 if (!cfdof) { 6719 for (b = 0; b < fdof; ++b) { 6720 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6721 const PetscInt ind = indperm ? indperm[preind] : preind; 6722 6723 indices[ind] = foff+b; 6724 } 6725 } else { 6726 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6727 for (b = 0; b < fdof; ++b) { 6728 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6729 const PetscInt ind = indperm ? indperm[preind] : preind; 6730 6731 if ((cind < cfdof) && (b == fcdofs[cind])) { 6732 indices[ind] = -(foff+b+1); 6733 ++cind; 6734 } else { 6735 indices[ind] = foff+b-cind; 6736 } 6737 } 6738 } 6739 foffs[f] += fdof; 6740 } 6741 PetscFunctionReturn(0); 6742 } 6743 6744 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) 6745 { 6746 Mat cMat; 6747 PetscSection aSec, cSec; 6748 IS aIS; 6749 PetscInt aStart = -1, aEnd = -1; 6750 const PetscInt *anchors; 6751 PetscInt numFields, f, p, q, newP = 0; 6752 PetscInt newNumPoints = 0, newNumIndices = 0; 6753 PetscInt *newPoints, *indices, *newIndices; 6754 PetscInt maxAnchor, maxDof; 6755 PetscInt newOffsets[32]; 6756 PetscInt *pointMatOffsets[32]; 6757 PetscInt *newPointOffsets[32]; 6758 PetscScalar *pointMat[32]; 6759 PetscScalar *newValues=NULL,*tmpValues; 6760 PetscBool anyConstrained = PETSC_FALSE; 6761 PetscErrorCode ierr; 6762 6763 PetscFunctionBegin; 6764 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6765 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6766 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6767 6768 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6769 /* if there are point-to-point constraints */ 6770 if (aSec) { 6771 ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr); 6772 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6773 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 6774 /* figure out how many points are going to be in the new element matrix 6775 * (we allow double counting, because it's all just going to be summed 6776 * into the global matrix anyway) */ 6777 for (p = 0; p < 2*numPoints; p+=2) { 6778 PetscInt b = points[p]; 6779 PetscInt bDof = 0, bSecDof; 6780 6781 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6782 if (!bSecDof) { 6783 continue; 6784 } 6785 if (b >= aStart && b < aEnd) { 6786 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 6787 } 6788 if (bDof) { 6789 /* this point is constrained */ 6790 /* it is going to be replaced by its anchors */ 6791 PetscInt bOff, q; 6792 6793 anyConstrained = PETSC_TRUE; 6794 newNumPoints += bDof; 6795 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 6796 for (q = 0; q < bDof; q++) { 6797 PetscInt a = anchors[bOff + q]; 6798 PetscInt aDof; 6799 6800 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6801 newNumIndices += aDof; 6802 for (f = 0; f < numFields; ++f) { 6803 PetscInt fDof; 6804 6805 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 6806 newOffsets[f+1] += fDof; 6807 } 6808 } 6809 } 6810 else { 6811 /* this point is not constrained */ 6812 newNumPoints++; 6813 newNumIndices += bSecDof; 6814 for (f = 0; f < numFields; ++f) { 6815 PetscInt fDof; 6816 6817 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6818 newOffsets[f+1] += fDof; 6819 } 6820 } 6821 } 6822 } 6823 if (!anyConstrained) { 6824 if (outNumPoints) *outNumPoints = 0; 6825 if (outNumIndices) *outNumIndices = 0; 6826 if (outPoints) *outPoints = NULL; 6827 if (outValues) *outValues = NULL; 6828 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6829 PetscFunctionReturn(0); 6830 } 6831 6832 if (outNumPoints) *outNumPoints = newNumPoints; 6833 if (outNumIndices) *outNumIndices = newNumIndices; 6834 6835 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6836 6837 if (!outPoints && !outValues) { 6838 if (offsets) { 6839 for (f = 0; f <= numFields; f++) { 6840 offsets[f] = newOffsets[f]; 6841 } 6842 } 6843 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6844 PetscFunctionReturn(0); 6845 } 6846 6847 PetscCheckFalse(numFields && newOffsets[numFields] != newNumIndices,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 6848 6849 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat, NULL);CHKERRQ(ierr); 6850 6851 /* workspaces */ 6852 if (numFields) { 6853 for (f = 0; f < numFields; f++) { 6854 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 6855 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6856 } 6857 } 6858 else { 6859 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 6860 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6861 } 6862 6863 /* get workspaces for the point-to-point matrices */ 6864 if (numFields) { 6865 PetscInt totalOffset, totalMatOffset; 6866 6867 for (p = 0; p < numPoints; p++) { 6868 PetscInt b = points[2*p]; 6869 PetscInt bDof = 0, bSecDof; 6870 6871 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6872 if (!bSecDof) { 6873 for (f = 0; f < numFields; f++) { 6874 newPointOffsets[f][p + 1] = 0; 6875 pointMatOffsets[f][p + 1] = 0; 6876 } 6877 continue; 6878 } 6879 if (b >= aStart && b < aEnd) { 6880 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6881 } 6882 if (bDof) { 6883 for (f = 0; f < numFields; f++) { 6884 PetscInt fDof, q, bOff, allFDof = 0; 6885 6886 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6887 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6888 for (q = 0; q < bDof; q++) { 6889 PetscInt a = anchors[bOff + q]; 6890 PetscInt aFDof; 6891 6892 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 6893 allFDof += aFDof; 6894 } 6895 newPointOffsets[f][p+1] = allFDof; 6896 pointMatOffsets[f][p+1] = fDof * allFDof; 6897 } 6898 } 6899 else { 6900 for (f = 0; f < numFields; f++) { 6901 PetscInt fDof; 6902 6903 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6904 newPointOffsets[f][p+1] = fDof; 6905 pointMatOffsets[f][p+1] = 0; 6906 } 6907 } 6908 } 6909 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 6910 newPointOffsets[f][0] = totalOffset; 6911 pointMatOffsets[f][0] = totalMatOffset; 6912 for (p = 0; p < numPoints; p++) { 6913 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6914 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6915 } 6916 totalOffset = newPointOffsets[f][numPoints]; 6917 totalMatOffset = pointMatOffsets[f][numPoints]; 6918 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 6919 } 6920 } 6921 else { 6922 for (p = 0; p < numPoints; p++) { 6923 PetscInt b = points[2*p]; 6924 PetscInt bDof = 0, bSecDof; 6925 6926 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6927 if (!bSecDof) { 6928 newPointOffsets[0][p + 1] = 0; 6929 pointMatOffsets[0][p + 1] = 0; 6930 continue; 6931 } 6932 if (b >= aStart && b < aEnd) { 6933 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6934 } 6935 if (bDof) { 6936 PetscInt bOff, q, allDof = 0; 6937 6938 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6939 for (q = 0; q < bDof; q++) { 6940 PetscInt a = anchors[bOff + q], aDof; 6941 6942 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 6943 allDof += aDof; 6944 } 6945 newPointOffsets[0][p+1] = allDof; 6946 pointMatOffsets[0][p+1] = bSecDof * allDof; 6947 } 6948 else { 6949 newPointOffsets[0][p+1] = bSecDof; 6950 pointMatOffsets[0][p+1] = 0; 6951 } 6952 } 6953 newPointOffsets[0][0] = 0; 6954 pointMatOffsets[0][0] = 0; 6955 for (p = 0; p < numPoints; p++) { 6956 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6957 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6958 } 6959 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 6960 } 6961 6962 /* output arrays */ 6963 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6964 6965 /* get the point-to-point matrices; construct newPoints */ 6966 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 6967 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6968 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 6969 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 6970 if (numFields) { 6971 for (p = 0, newP = 0; p < numPoints; p++) { 6972 PetscInt b = points[2*p]; 6973 PetscInt o = points[2*p+1]; 6974 PetscInt bDof = 0, bSecDof; 6975 6976 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6977 if (!bSecDof) { 6978 continue; 6979 } 6980 if (b >= aStart && b < aEnd) { 6981 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6982 } 6983 if (bDof) { 6984 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6985 6986 fStart[0] = 0; 6987 fEnd[0] = 0; 6988 for (f = 0; f < numFields; f++) { 6989 PetscInt fDof; 6990 6991 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 6992 fStart[f+1] = fStart[f] + fDof; 6993 fEnd[f+1] = fStart[f+1]; 6994 } 6995 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6996 ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 6997 6998 fAnchorStart[0] = 0; 6999 fAnchorEnd[0] = 0; 7000 for (f = 0; f < numFields; f++) { 7001 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 7002 7003 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 7004 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 7005 } 7006 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 7007 for (q = 0; q < bDof; q++) { 7008 PetscInt a = anchors[bOff + q], aOff; 7009 7010 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 7011 newPoints[2*(newP + q)] = a; 7012 newPoints[2*(newP + q) + 1] = 0; 7013 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 7014 ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 7015 } 7016 newP += bDof; 7017 7018 if (outValues) { 7019 /* get the point-to-point submatrix */ 7020 for (f = 0; f < numFields; f++) { 7021 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 7022 } 7023 } 7024 } 7025 else { 7026 newPoints[2 * newP] = b; 7027 newPoints[2 * newP + 1] = o; 7028 newP++; 7029 } 7030 } 7031 } else { 7032 for (p = 0; p < numPoints; p++) { 7033 PetscInt b = points[2*p]; 7034 PetscInt o = points[2*p+1]; 7035 PetscInt bDof = 0, bSecDof; 7036 7037 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 7038 if (!bSecDof) { 7039 continue; 7040 } 7041 if (b >= aStart && b < aEnd) { 7042 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 7043 } 7044 if (bDof) { 7045 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7046 7047 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 7048 ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 7049 7050 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 7051 for (q = 0; q < bDof; q++) { 7052 PetscInt a = anchors[bOff + q], aOff; 7053 7054 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 7055 7056 newPoints[2*(newP + q)] = a; 7057 newPoints[2*(newP + q) + 1] = 0; 7058 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 7059 ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 7060 } 7061 newP += bDof; 7062 7063 /* get the point-to-point submatrix */ 7064 if (outValues) { 7065 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 7066 } 7067 } 7068 else { 7069 newPoints[2 * newP] = b; 7070 newPoints[2 * newP + 1] = o; 7071 newP++; 7072 } 7073 } 7074 } 7075 7076 if (outValues) { 7077 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7078 ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr); 7079 /* multiply constraints on the right */ 7080 if (numFields) { 7081 for (f = 0; f < numFields; f++) { 7082 PetscInt oldOff = offsets[f]; 7083 7084 for (p = 0; p < numPoints; p++) { 7085 PetscInt cStart = newPointOffsets[f][p]; 7086 PetscInt b = points[2 * p]; 7087 PetscInt c, r, k; 7088 PetscInt dof; 7089 7090 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7091 if (!dof) { 7092 continue; 7093 } 7094 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7095 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 7096 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7097 7098 for (r = 0; r < numIndices; r++) { 7099 for (c = 0; c < nCols; c++) { 7100 for (k = 0; k < dof; k++) { 7101 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7102 } 7103 } 7104 } 7105 } 7106 else { 7107 /* copy this column as is */ 7108 for (r = 0; r < numIndices; r++) { 7109 for (c = 0; c < dof; c++) { 7110 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7111 } 7112 } 7113 } 7114 oldOff += dof; 7115 } 7116 } 7117 } 7118 else { 7119 PetscInt oldOff = 0; 7120 for (p = 0; p < numPoints; p++) { 7121 PetscInt cStart = newPointOffsets[0][p]; 7122 PetscInt b = points[2 * p]; 7123 PetscInt c, r, k; 7124 PetscInt dof; 7125 7126 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7127 if (!dof) { 7128 continue; 7129 } 7130 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7131 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 7132 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7133 7134 for (r = 0; r < numIndices; r++) { 7135 for (c = 0; c < nCols; c++) { 7136 for (k = 0; k < dof; k++) { 7137 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7138 } 7139 } 7140 } 7141 } 7142 else { 7143 /* copy this column as is */ 7144 for (r = 0; r < numIndices; r++) { 7145 for (c = 0; c < dof; c++) { 7146 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7147 } 7148 } 7149 } 7150 oldOff += dof; 7151 } 7152 } 7153 7154 if (multiplyLeft) { 7155 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 7156 ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr); 7157 /* multiply constraints transpose on the left */ 7158 if (numFields) { 7159 for (f = 0; f < numFields; f++) { 7160 PetscInt oldOff = offsets[f]; 7161 7162 for (p = 0; p < numPoints; p++) { 7163 PetscInt rStart = newPointOffsets[f][p]; 7164 PetscInt b = points[2 * p]; 7165 PetscInt c, r, k; 7166 PetscInt dof; 7167 7168 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7169 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7170 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 7171 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7172 7173 for (r = 0; r < nRows; r++) { 7174 for (c = 0; c < newNumIndices; c++) { 7175 for (k = 0; k < dof; k++) { 7176 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7177 } 7178 } 7179 } 7180 } 7181 else { 7182 /* copy this row as is */ 7183 for (r = 0; r < dof; r++) { 7184 for (c = 0; c < newNumIndices; c++) { 7185 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7186 } 7187 } 7188 } 7189 oldOff += dof; 7190 } 7191 } 7192 } 7193 else { 7194 PetscInt oldOff = 0; 7195 7196 for (p = 0; p < numPoints; p++) { 7197 PetscInt rStart = newPointOffsets[0][p]; 7198 PetscInt b = points[2 * p]; 7199 PetscInt c, r, k; 7200 PetscInt dof; 7201 7202 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7203 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7204 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 7205 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7206 7207 for (r = 0; r < nRows; r++) { 7208 for (c = 0; c < newNumIndices; c++) { 7209 for (k = 0; k < dof; k++) { 7210 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7211 } 7212 } 7213 } 7214 } 7215 else { 7216 /* copy this row as is */ 7217 for (r = 0; r < dof; r++) { 7218 for (c = 0; c < newNumIndices; c++) { 7219 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7220 } 7221 } 7222 } 7223 oldOff += dof; 7224 } 7225 } 7226 7227 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7228 } 7229 else { 7230 newValues = tmpValues; 7231 } 7232 } 7233 7234 /* clean up */ 7235 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 7236 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 7237 7238 if (numFields) { 7239 for (f = 0; f < numFields; f++) { 7240 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 7241 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 7242 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 7243 } 7244 } 7245 else { 7246 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 7247 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 7248 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 7249 } 7250 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7251 7252 /* output */ 7253 if (outPoints) { 7254 *outPoints = newPoints; 7255 } 7256 else { 7257 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 7258 } 7259 if (outValues) { 7260 *outValues = newValues; 7261 } 7262 for (f = 0; f <= numFields; f++) { 7263 offsets[f] = newOffsets[f]; 7264 } 7265 PetscFunctionReturn(0); 7266 } 7267 7268 /*@C 7269 DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 7270 7271 Not collective 7272 7273 Input Parameters: 7274 + dm - The DM 7275 . section - The PetscSection describing the points (a local section) 7276 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7277 . point - The point defining the closure 7278 - useClPerm - Use the closure point permutation if available 7279 7280 Output Parameters: 7281 + numIndices - The number of dof indices in the closure of point with the input sections 7282 . indices - The dof indices 7283 . outOffsets - Array to write the field offsets into, or NULL 7284 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7285 7286 Notes: 7287 Must call DMPlexRestoreClosureIndices() to free allocated memory 7288 7289 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7290 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7291 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7292 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7293 indices (with the above semantics) are implied. 7294 7295 Level: advanced 7296 7297 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7298 @*/ 7299 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7300 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7301 { 7302 /* Closure ordering */ 7303 PetscSection clSection; 7304 IS clPoints; 7305 const PetscInt *clp; 7306 PetscInt *points; 7307 const PetscInt *clperm = NULL; 7308 /* Dof permutation and sign flips */ 7309 const PetscInt **perms[32] = {NULL}; 7310 const PetscScalar **flips[32] = {NULL}; 7311 PetscScalar *valCopy = NULL; 7312 /* Hanging node constraints */ 7313 PetscInt *pointsC = NULL; 7314 PetscScalar *valuesC = NULL; 7315 PetscInt NclC, NiC; 7316 7317 PetscInt *idx; 7318 PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 7319 PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 7320 PetscErrorCode ierr; 7321 7322 PetscFunctionBeginHot; 7323 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7324 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7325 PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7326 if (numIndices) PetscValidPointer(numIndices, 6); 7327 if (indices) PetscValidPointer(indices, 7); 7328 if (outOffsets) PetscValidPointer(outOffsets, 8); 7329 if (values) PetscValidPointer(values, 9); 7330 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 7331 PetscCheckFalse(Nf > 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 7332 ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 7333 /* 1) Get points in closure */ 7334 ierr = DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7335 if (useClPerm) { 7336 PetscInt depth, clsize; 7337 ierr = DMPlexGetPointDepth(dm, point, &depth);CHKERRQ(ierr); 7338 for (clsize=0,p=0; p<Ncl; p++) { 7339 PetscInt dof; 7340 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 7341 clsize += dof; 7342 } 7343 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 7344 } 7345 /* 2) Get number of indices on these points and field offsets from section */ 7346 for (p = 0; p < Ncl*2; p += 2) { 7347 PetscInt dof, fdof; 7348 7349 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7350 for (f = 0; f < Nf; ++f) { 7351 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7352 offsets[f+1] += fdof; 7353 } 7354 Ni += dof; 7355 } 7356 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 7357 PetscCheckFalse(Nf && offsets[Nf] != Ni,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni); 7358 /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 7359 for (f = 0; f < PetscMax(1, Nf); ++f) { 7360 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7361 else {ierr = PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7362 /* may need to apply sign changes to the element matrix */ 7363 if (values && flips[f]) { 7364 PetscInt foffset = offsets[f]; 7365 7366 for (p = 0; p < Ncl; ++p) { 7367 PetscInt pnt = points[2*p], fdof; 7368 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 7369 7370 if (!Nf) {ierr = PetscSectionGetDof(section, pnt, &fdof);CHKERRQ(ierr);} 7371 else {ierr = PetscSectionGetFieldDof(section, pnt, f, &fdof);CHKERRQ(ierr);} 7372 if (flip) { 7373 PetscInt i, j, k; 7374 7375 if (!valCopy) { 7376 ierr = DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr); 7377 for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 7378 *values = valCopy; 7379 } 7380 for (i = 0; i < fdof; ++i) { 7381 PetscScalar fval = flip[i]; 7382 7383 for (k = 0; k < Ni; ++k) { 7384 valCopy[Ni * (foffset + i) + k] *= fval; 7385 valCopy[Ni * k + (foffset + i)] *= fval; 7386 } 7387 } 7388 } 7389 foffset += fdof; 7390 } 7391 } 7392 } 7393 /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 7394 ierr = DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 7395 if (NclC) { 7396 if (valCopy) {ierr = DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);} 7397 for (f = 0; f < PetscMax(1, Nf); ++f) { 7398 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7399 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7400 } 7401 for (f = 0; f < PetscMax(1, Nf); ++f) { 7402 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7403 else {ierr = PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7404 } 7405 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7406 Ncl = NclC; 7407 Ni = NiC; 7408 points = pointsC; 7409 if (values) *values = valuesC; 7410 } 7411 /* 5) Calculate indices */ 7412 ierr = DMGetWorkArray(dm, Ni, MPIU_INT, &idx);CHKERRQ(ierr); 7413 if (Nf) { 7414 PetscInt idxOff; 7415 PetscBool useFieldOffsets; 7416 7417 if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 7418 ierr = PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets);CHKERRQ(ierr); 7419 if (useFieldOffsets) { 7420 for (p = 0; p < Ncl; ++p) { 7421 const PetscInt pnt = points[p*2]; 7422 7423 ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx);CHKERRQ(ierr); 7424 } 7425 } else { 7426 for (p = 0; p < Ncl; ++p) { 7427 const PetscInt pnt = points[p*2]; 7428 7429 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7430 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7431 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 7432 * global section. */ 7433 ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx);CHKERRQ(ierr); 7434 } 7435 } 7436 } else { 7437 PetscInt off = 0, idxOff; 7438 7439 for (p = 0; p < Ncl; ++p) { 7440 const PetscInt pnt = points[p*2]; 7441 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 7442 7443 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7444 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7445 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 7446 ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx);CHKERRQ(ierr); 7447 } 7448 } 7449 /* 6) Cleanup */ 7450 for (f = 0; f < PetscMax(1, Nf); ++f) { 7451 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7452 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7453 } 7454 if (NclC) { 7455 ierr = DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC);CHKERRQ(ierr); 7456 } else { 7457 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7458 } 7459 7460 if (numIndices) *numIndices = Ni; 7461 if (indices) *indices = idx; 7462 PetscFunctionReturn(0); 7463 } 7464 7465 /*@C 7466 DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 7467 7468 Not collective 7469 7470 Input Parameters: 7471 + dm - The DM 7472 . section - The PetscSection describing the points (a local section) 7473 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7474 . point - The point defining the closure 7475 - useClPerm - Use the closure point permutation if available 7476 7477 Output Parameters: 7478 + numIndices - The number of dof indices in the closure of point with the input sections 7479 . indices - The dof indices 7480 . outOffsets - Array to write the field offsets into, or NULL 7481 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7482 7483 Notes: 7484 If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 7485 7486 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7487 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7488 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7489 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7490 indices (with the above semantics) are implied. 7491 7492 Level: advanced 7493 7494 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7495 @*/ 7496 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7497 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7498 { 7499 PetscErrorCode ierr; 7500 7501 PetscFunctionBegin; 7502 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7503 PetscValidPointer(indices, 7); 7504 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 7505 PetscFunctionReturn(0); 7506 } 7507 7508 /*@C 7509 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 7510 7511 Not collective 7512 7513 Input Parameters: 7514 + dm - The DM 7515 . section - The section describing the layout in v, or NULL to use the default section 7516 . globalSection - The section describing the layout in v, or NULL to use the default global section 7517 . A - The matrix 7518 . point - The point in the DM 7519 . values - The array of values 7520 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7521 7522 Fortran Notes: 7523 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 7524 7525 Level: intermediate 7526 7527 .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7528 @*/ 7529 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7530 { 7531 DM_Plex *mesh = (DM_Plex*) dm->data; 7532 PetscInt *indices; 7533 PetscInt numIndices; 7534 const PetscScalar *valuesOrig = values; 7535 PetscErrorCode ierr; 7536 7537 PetscFunctionBegin; 7538 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7539 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 7540 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7541 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 7542 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 7543 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7544 7545 ierr = DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7546 7547 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 7548 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7549 if (ierr) { 7550 PetscMPIInt rank; 7551 PetscErrorCode ierr2; 7552 7553 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7554 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7555 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 7556 ierr2 = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7557 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7558 SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values"); 7559 } 7560 if (mesh->printFEM > 1) { 7561 PetscInt i; 7562 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 7563 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 7564 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7565 } 7566 7567 ierr = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7568 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7569 PetscFunctionReturn(0); 7570 } 7571 7572 /*@C 7573 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 7574 7575 Not collective 7576 7577 Input Parameters: 7578 + dmRow - The DM for the row fields 7579 . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 7580 . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 7581 . dmCol - The DM for the column fields 7582 . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 7583 . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 7584 . A - The matrix 7585 . point - The point in the DMs 7586 . values - The array of values 7587 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7588 7589 Level: intermediate 7590 7591 .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7592 @*/ 7593 PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7594 { 7595 DM_Plex *mesh = (DM_Plex*) dmRow->data; 7596 PetscInt *indicesRow, *indicesCol; 7597 PetscInt numIndicesRow, numIndicesCol; 7598 const PetscScalar *valuesOrig = values; 7599 PetscErrorCode ierr; 7600 7601 PetscFunctionBegin; 7602 PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 7603 if (!sectionRow) {ierr = DMGetLocalSection(dmRow, §ionRow);CHKERRQ(ierr);} 7604 PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 7605 if (!globalSectionRow) {ierr = DMGetGlobalSection(dmRow, &globalSectionRow);CHKERRQ(ierr);} 7606 PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 7607 PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 7608 if (!sectionCol) {ierr = DMGetLocalSection(dmCol, §ionCol);CHKERRQ(ierr);} 7609 PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 7610 if (!globalSectionCol) {ierr = DMGetGlobalSection(dmCol, &globalSectionCol);CHKERRQ(ierr);} 7611 PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 7612 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7613 7614 ierr = DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7615 ierr = DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7616 7617 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr);} 7618 ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 7619 if (ierr) { 7620 PetscMPIInt rank; 7621 PetscErrorCode ierr2; 7622 7623 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7624 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7625 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr2); 7626 ierr2 = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7627 ierr2 = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7628 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7629 CHKERRQ(ierr); 7630 } 7631 7632 ierr = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7633 ierr = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7634 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7635 PetscFunctionReturn(0); 7636 } 7637 7638 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7639 { 7640 DM_Plex *mesh = (DM_Plex*) dmf->data; 7641 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7642 PetscInt *cpoints = NULL; 7643 PetscInt *findices, *cindices; 7644 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7645 PetscInt foffsets[32], coffsets[32]; 7646 DMPolytopeType ct; 7647 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7648 PetscErrorCode ierr; 7649 7650 PetscFunctionBegin; 7651 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7652 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7653 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7654 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7655 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7656 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7657 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7658 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7659 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7660 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7661 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7662 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7663 PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7664 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7665 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7666 /* Column indices */ 7667 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7668 maxFPoints = numCPoints; 7669 /* Compress out points not in the section */ 7670 /* TODO: Squeeze out points with 0 dof as well */ 7671 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7672 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7673 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7674 cpoints[q*2] = cpoints[p]; 7675 cpoints[q*2+1] = cpoints[p+1]; 7676 ++q; 7677 } 7678 } 7679 numCPoints = q; 7680 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7681 PetscInt fdof; 7682 7683 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7684 if (!dof) continue; 7685 for (f = 0; f < numFields; ++f) { 7686 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7687 coffsets[f+1] += fdof; 7688 } 7689 numCIndices += dof; 7690 } 7691 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7692 /* Row indices */ 7693 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7694 { 7695 DMPlexTransform tr; 7696 DMPolytopeType *rct; 7697 PetscInt *rsize, *rcone, *rornt, Nt; 7698 7699 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7700 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7701 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7702 numSubcells = rsize[Nt-1]; 7703 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7704 } 7705 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7706 for (r = 0, q = 0; r < numSubcells; ++r) { 7707 /* TODO Map from coarse to fine cells */ 7708 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7709 /* Compress out points not in the section */ 7710 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7711 for (p = 0; p < numFPoints*2; p += 2) { 7712 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7713 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7714 if (!dof) continue; 7715 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7716 if (s < q) continue; 7717 ftotpoints[q*2] = fpoints[p]; 7718 ftotpoints[q*2+1] = fpoints[p+1]; 7719 ++q; 7720 } 7721 } 7722 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7723 } 7724 numFPoints = q; 7725 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7726 PetscInt fdof; 7727 7728 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7729 if (!dof) continue; 7730 for (f = 0; f < numFields; ++f) { 7731 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7732 foffsets[f+1] += fdof; 7733 } 7734 numFIndices += dof; 7735 } 7736 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7737 7738 PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7739 PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7740 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7741 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7742 if (numFields) { 7743 const PetscInt **permsF[32] = {NULL}; 7744 const PetscInt **permsC[32] = {NULL}; 7745 7746 for (f = 0; f < numFields; f++) { 7747 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7748 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7749 } 7750 for (p = 0; p < numFPoints; p++) { 7751 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7752 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7753 } 7754 for (p = 0; p < numCPoints; p++) { 7755 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7756 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7757 } 7758 for (f = 0; f < numFields; f++) { 7759 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7760 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7761 } 7762 } else { 7763 const PetscInt **permsF = NULL; 7764 const PetscInt **permsC = NULL; 7765 7766 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7767 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7768 for (p = 0, off = 0; p < numFPoints; p++) { 7769 const PetscInt *perm = permsF ? permsF[p] : NULL; 7770 7771 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7772 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7773 } 7774 for (p = 0, off = 0; p < numCPoints; p++) { 7775 const PetscInt *perm = permsC ? permsC[p] : NULL; 7776 7777 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7778 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7779 } 7780 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7781 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7782 } 7783 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 7784 /* TODO: flips */ 7785 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7786 if (ierr) { 7787 PetscMPIInt rank; 7788 PetscErrorCode ierr2; 7789 7790 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7791 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7792 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 7793 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 7794 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 7795 CHKERRQ(ierr); 7796 } 7797 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7798 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7799 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7800 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7801 PetscFunctionReturn(0); 7802 } 7803 7804 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 7805 { 7806 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7807 PetscInt *cpoints = NULL; 7808 PetscInt foffsets[32], coffsets[32]; 7809 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7810 DMPolytopeType ct; 7811 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7812 PetscErrorCode ierr; 7813 7814 PetscFunctionBegin; 7815 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7816 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7817 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7818 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7819 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7820 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7821 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7822 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7823 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7824 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7825 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7826 PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7827 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7828 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7829 /* Column indices */ 7830 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7831 maxFPoints = numCPoints; 7832 /* Compress out points not in the section */ 7833 /* TODO: Squeeze out points with 0 dof as well */ 7834 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7835 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7836 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7837 cpoints[q*2] = cpoints[p]; 7838 cpoints[q*2+1] = cpoints[p+1]; 7839 ++q; 7840 } 7841 } 7842 numCPoints = q; 7843 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7844 PetscInt fdof; 7845 7846 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7847 if (!dof) continue; 7848 for (f = 0; f < numFields; ++f) { 7849 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7850 coffsets[f+1] += fdof; 7851 } 7852 numCIndices += dof; 7853 } 7854 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7855 /* Row indices */ 7856 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7857 { 7858 DMPlexTransform tr; 7859 DMPolytopeType *rct; 7860 PetscInt *rsize, *rcone, *rornt, Nt; 7861 7862 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7863 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7864 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7865 numSubcells = rsize[Nt-1]; 7866 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7867 } 7868 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7869 for (r = 0, q = 0; r < numSubcells; ++r) { 7870 /* TODO Map from coarse to fine cells */ 7871 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7872 /* Compress out points not in the section */ 7873 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7874 for (p = 0; p < numFPoints*2; p += 2) { 7875 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7876 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7877 if (!dof) continue; 7878 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7879 if (s < q) continue; 7880 ftotpoints[q*2] = fpoints[p]; 7881 ftotpoints[q*2+1] = fpoints[p+1]; 7882 ++q; 7883 } 7884 } 7885 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7886 } 7887 numFPoints = q; 7888 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7889 PetscInt fdof; 7890 7891 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7892 if (!dof) continue; 7893 for (f = 0; f < numFields; ++f) { 7894 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7895 foffsets[f+1] += fdof; 7896 } 7897 numFIndices += dof; 7898 } 7899 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7900 7901 PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7902 PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7903 if (numFields) { 7904 const PetscInt **permsF[32] = {NULL}; 7905 const PetscInt **permsC[32] = {NULL}; 7906 7907 for (f = 0; f < numFields; f++) { 7908 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7909 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7910 } 7911 for (p = 0; p < numFPoints; p++) { 7912 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7913 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7914 } 7915 for (p = 0; p < numCPoints; p++) { 7916 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7917 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7918 } 7919 for (f = 0; f < numFields; f++) { 7920 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7921 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7922 } 7923 } else { 7924 const PetscInt **permsF = NULL; 7925 const PetscInt **permsC = NULL; 7926 7927 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7928 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7929 for (p = 0, off = 0; p < numFPoints; p++) { 7930 const PetscInt *perm = permsF ? permsF[p] : NULL; 7931 7932 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7933 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7934 } 7935 for (p = 0, off = 0; p < numCPoints; p++) { 7936 const PetscInt *perm = permsC ? permsC[p] : NULL; 7937 7938 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7939 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7940 } 7941 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7942 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7943 } 7944 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7945 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7946 PetscFunctionReturn(0); 7947 } 7948 7949 /*@C 7950 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 7951 7952 Input Parameter: 7953 . dm - The DMPlex object 7954 7955 Output Parameter: 7956 . cellHeight - The height of a cell 7957 7958 Level: developer 7959 7960 .seealso DMPlexSetVTKCellHeight() 7961 @*/ 7962 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7963 { 7964 DM_Plex *mesh = (DM_Plex*) dm->data; 7965 7966 PetscFunctionBegin; 7967 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7968 PetscValidPointer(cellHeight, 2); 7969 *cellHeight = mesh->vtkCellHeight; 7970 PetscFunctionReturn(0); 7971 } 7972 7973 /*@C 7974 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 7975 7976 Input Parameters: 7977 + dm - The DMPlex object 7978 - cellHeight - The height of a cell 7979 7980 Level: developer 7981 7982 .seealso DMPlexGetVTKCellHeight() 7983 @*/ 7984 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7985 { 7986 DM_Plex *mesh = (DM_Plex*) dm->data; 7987 7988 PetscFunctionBegin; 7989 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7990 mesh->vtkCellHeight = cellHeight; 7991 PetscFunctionReturn(0); 7992 } 7993 7994 /*@ 7995 DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 7996 7997 Input Parameter: 7998 . dm - The DMPlex object 7999 8000 Output Parameters: 8001 + gcStart - The first ghost cell, or NULL 8002 - gcEnd - The upper bound on ghost cells, or NULL 8003 8004 Level: advanced 8005 8006 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 8007 @*/ 8008 PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 8009 { 8010 DMLabel ctLabel; 8011 PetscErrorCode ierr; 8012 8013 PetscFunctionBegin; 8014 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8015 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 8016 ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr); 8017 PetscFunctionReturn(0); 8018 } 8019 8020 PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8021 { 8022 PetscSection section, globalSection; 8023 PetscInt *numbers, p; 8024 PetscErrorCode ierr; 8025 8026 PetscFunctionBegin; 8027 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 8028 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 8029 for (p = pStart; p < pEnd; ++p) { 8030 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 8031 } 8032 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 8033 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8034 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 8035 for (p = pStart; p < pEnd; ++p) { 8036 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 8037 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 8038 else numbers[p-pStart] += shift; 8039 } 8040 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 8041 if (globalSize) { 8042 PetscLayout layout; 8043 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 8044 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 8045 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 8046 } 8047 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 8048 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8049 PetscFunctionReturn(0); 8050 } 8051 8052 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8053 { 8054 PetscInt cellHeight, cStart, cEnd; 8055 PetscErrorCode ierr; 8056 8057 PetscFunctionBegin; 8058 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8059 if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 8060 else {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 8061 ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 8062 PetscFunctionReturn(0); 8063 } 8064 8065 /*@ 8066 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 8067 8068 Input Parameter: 8069 . dm - The DMPlex object 8070 8071 Output Parameter: 8072 . globalCellNumbers - Global cell numbers for all cells on this process 8073 8074 Level: developer 8075 8076 .seealso DMPlexGetVertexNumbering() 8077 @*/ 8078 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8079 { 8080 DM_Plex *mesh = (DM_Plex*) dm->data; 8081 PetscErrorCode ierr; 8082 8083 PetscFunctionBegin; 8084 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8085 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 8086 *globalCellNumbers = mesh->globalCellNumbers; 8087 PetscFunctionReturn(0); 8088 } 8089 8090 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8091 { 8092 PetscInt vStart, vEnd; 8093 PetscErrorCode ierr; 8094 8095 PetscFunctionBegin; 8096 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8097 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8098 ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 8099 PetscFunctionReturn(0); 8100 } 8101 8102 /*@ 8103 DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 8104 8105 Input Parameter: 8106 . dm - The DMPlex object 8107 8108 Output Parameter: 8109 . globalVertexNumbers - Global vertex numbers for all vertices on this process 8110 8111 Level: developer 8112 8113 .seealso DMPlexGetCellNumbering() 8114 @*/ 8115 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8116 { 8117 DM_Plex *mesh = (DM_Plex*) dm->data; 8118 PetscErrorCode ierr; 8119 8120 PetscFunctionBegin; 8121 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8122 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 8123 *globalVertexNumbers = mesh->globalVertexNumbers; 8124 PetscFunctionReturn(0); 8125 } 8126 8127 /*@ 8128 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 8129 8130 Input Parameter: 8131 . dm - The DMPlex object 8132 8133 Output Parameter: 8134 . globalPointNumbers - Global numbers for all points on this process 8135 8136 Level: developer 8137 8138 .seealso DMPlexGetCellNumbering() 8139 @*/ 8140 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8141 { 8142 IS nums[4]; 8143 PetscInt depths[4], gdepths[4], starts[4]; 8144 PetscInt depth, d, shift = 0; 8145 PetscErrorCode ierr; 8146 8147 PetscFunctionBegin; 8148 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8149 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8150 /* For unstratified meshes use dim instead of depth */ 8151 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 8152 for (d = 0; d <= depth; ++d) { 8153 PetscInt end; 8154 8155 depths[d] = depth-d; 8156 ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 8157 if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 8158 } 8159 ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 8160 ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 8161 for (d = 0; d <= depth; ++d) { 8162 PetscCheckFalse(starts[d] >= 0 && depths[d] != gdepths[d],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 8163 } 8164 for (d = 0; d <= depth; ++d) { 8165 PetscInt pStart, pEnd, gsize; 8166 8167 ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 8168 ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 8169 shift += gsize; 8170 } 8171 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 8172 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 8173 PetscFunctionReturn(0); 8174 } 8175 8176 /*@ 8177 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 8178 8179 Input Parameter: 8180 . dm - The DMPlex object 8181 8182 Output Parameter: 8183 . ranks - The rank field 8184 8185 Options Database Keys: 8186 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 8187 8188 Level: intermediate 8189 8190 .seealso: DMView() 8191 @*/ 8192 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8193 { 8194 DM rdm; 8195 PetscFE fe; 8196 PetscScalar *r; 8197 PetscMPIInt rank; 8198 DMPolytopeType ct; 8199 PetscInt dim, cStart, cEnd, c; 8200 PetscBool simplex; 8201 PetscErrorCode ierr; 8202 8203 PetscFunctionBeginUser; 8204 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8205 PetscValidPointer(ranks, 2); 8206 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 8207 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8208 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8209 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8210 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 8211 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 8212 ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 8213 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 8214 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8215 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8216 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8217 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 8218 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 8219 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 8220 for (c = cStart; c < cEnd; ++c) { 8221 PetscScalar *lr; 8222 8223 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 8224 if (lr) *lr = rank; 8225 } 8226 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 8227 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8228 PetscFunctionReturn(0); 8229 } 8230 8231 /*@ 8232 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 8233 8234 Input Parameters: 8235 + dm - The DMPlex 8236 - label - The DMLabel 8237 8238 Output Parameter: 8239 . val - The label value field 8240 8241 Options Database Keys: 8242 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 8243 8244 Level: intermediate 8245 8246 .seealso: DMView() 8247 @*/ 8248 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8249 { 8250 DM rdm; 8251 PetscFE fe; 8252 PetscScalar *v; 8253 PetscInt dim, cStart, cEnd, c; 8254 PetscErrorCode ierr; 8255 8256 PetscFunctionBeginUser; 8257 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8258 PetscValidPointer(label, 2); 8259 PetscValidPointer(val, 3); 8260 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8261 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8262 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 8263 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 8264 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8265 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8266 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8267 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8268 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 8269 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 8270 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 8271 for (c = cStart; c < cEnd; ++c) { 8272 PetscScalar *lv; 8273 PetscInt cval; 8274 8275 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 8276 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 8277 *lv = cval; 8278 } 8279 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 8280 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8281 PetscFunctionReturn(0); 8282 } 8283 8284 /*@ 8285 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8286 8287 Input Parameter: 8288 . dm - The DMPlex object 8289 8290 Notes: 8291 This is a useful diagnostic when creating meshes programmatically. 8292 8293 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8294 8295 Level: developer 8296 8297 .seealso: DMCreate(), DMSetFromOptions() 8298 @*/ 8299 PetscErrorCode DMPlexCheckSymmetry(DM dm) 8300 { 8301 PetscSection coneSection, supportSection; 8302 const PetscInt *cone, *support; 8303 PetscInt coneSize, c, supportSize, s; 8304 PetscInt pStart, pEnd, p, pp, csize, ssize; 8305 PetscBool storagecheck = PETSC_TRUE; 8306 PetscErrorCode ierr; 8307 8308 PetscFunctionBegin; 8309 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8310 ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr); 8311 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 8312 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 8313 /* Check that point p is found in the support of its cone points, and vice versa */ 8314 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8315 for (p = pStart; p < pEnd; ++p) { 8316 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8317 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8318 for (c = 0; c < coneSize; ++c) { 8319 PetscBool dup = PETSC_FALSE; 8320 PetscInt d; 8321 for (d = c-1; d >= 0; --d) { 8322 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 8323 } 8324 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 8325 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 8326 for (s = 0; s < supportSize; ++s) { 8327 if (support[s] == p) break; 8328 } 8329 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 8330 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 8331 for (s = 0; s < coneSize; ++s) { 8332 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 8333 } 8334 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8335 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 8336 for (s = 0; s < supportSize; ++s) { 8337 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 8338 } 8339 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8340 PetscCheckFalse(dup,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 8341 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 8342 } 8343 } 8344 ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 8345 if (p != pp) { storagecheck = PETSC_FALSE; continue; } 8346 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 8347 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 8348 for (s = 0; s < supportSize; ++s) { 8349 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 8350 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 8351 for (c = 0; c < coneSize; ++c) { 8352 ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 8353 if (cone[c] != pp) { c = 0; break; } 8354 if (cone[c] == p) break; 8355 } 8356 if (c >= coneSize) { 8357 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 8358 for (c = 0; c < supportSize; ++c) { 8359 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 8360 } 8361 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8362 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 8363 for (c = 0; c < coneSize; ++c) { 8364 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 8365 } 8366 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8367 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 8368 } 8369 } 8370 } 8371 if (storagecheck) { 8372 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 8373 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 8374 PetscCheckFalse(csize != ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 8375 } 8376 PetscFunctionReturn(0); 8377 } 8378 8379 /* 8380 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. 8381 */ 8382 static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8383 { 8384 DMPolytopeType cct; 8385 PetscInt ptpoints[4]; 8386 const PetscInt *cone, *ccone, *ptcone; 8387 PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8388 PetscErrorCode ierr; 8389 8390 PetscFunctionBegin; 8391 *unsplit = 0; 8392 switch (ct) { 8393 case DM_POLYTOPE_POINT_PRISM_TENSOR: 8394 ptpoints[npt++] = c; 8395 break; 8396 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8397 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8398 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8399 for (cp = 0; cp < coneSize; ++cp) { 8400 ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr); 8401 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8402 } 8403 break; 8404 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8405 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8406 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8407 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8408 for (cp = 0; cp < coneSize; ++cp) { 8409 ierr = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr); 8410 ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr); 8411 for (ccp = 0; ccp < cconeSize; ++ccp) { 8412 ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr); 8413 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8414 PetscInt p; 8415 for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8416 if (p == npt) ptpoints[npt++] = ccone[ccp]; 8417 } 8418 } 8419 } 8420 break; 8421 default: break; 8422 } 8423 for (pt = 0; pt < npt; ++pt) { 8424 ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr); 8425 if (ptcone[0] == ptcone[1]) ++(*unsplit); 8426 } 8427 PetscFunctionReturn(0); 8428 } 8429 8430 /*@ 8431 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8432 8433 Input Parameters: 8434 + dm - The DMPlex object 8435 - cellHeight - Normally 0 8436 8437 Notes: 8438 This is a useful diagnostic when creating meshes programmatically. 8439 Currently applicable only to homogeneous simplex or tensor meshes. 8440 8441 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8442 8443 Level: developer 8444 8445 .seealso: DMCreate(), DMSetFromOptions() 8446 @*/ 8447 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8448 { 8449 DMPlexInterpolatedFlag interp; 8450 DMPolytopeType ct; 8451 PetscInt vStart, vEnd, cStart, cEnd, c; 8452 PetscErrorCode ierr; 8453 8454 PetscFunctionBegin; 8455 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8456 ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr); 8457 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8458 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8459 for (c = cStart; c < cEnd; ++c) { 8460 PetscInt *closure = NULL; 8461 PetscInt coneSize, closureSize, cl, Nv = 0; 8462 8463 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8464 PetscCheckFalse((PetscInt) ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c); 8465 if (ct == DM_POLYTOPE_UNKNOWN) continue; 8466 if (interp == DMPLEX_INTERPOLATED_FULL) { 8467 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8468 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)); 8469 } 8470 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8471 for (cl = 0; cl < closureSize*2; cl += 2) { 8472 const PetscInt p = closure[cl]; 8473 if ((p >= vStart) && (p < vEnd)) ++Nv; 8474 } 8475 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8476 /* Special Case: Tensor faces with identified vertices */ 8477 if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8478 PetscInt unsplit; 8479 8480 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8481 if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 8482 } 8483 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)); 8484 } 8485 PetscFunctionReturn(0); 8486 } 8487 8488 /*@ 8489 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 8490 8491 Not Collective 8492 8493 Input Parameters: 8494 + dm - The DMPlex object 8495 - cellHeight - Normally 0 8496 8497 Notes: 8498 This is a useful diagnostic when creating meshes programmatically. 8499 This routine is only relevant for meshes that are fully interpolated across all ranks. 8500 It will error out if a partially interpolated mesh is given on some rank. 8501 It will do nothing for locally uninterpolated mesh (as there is nothing to check). 8502 8503 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8504 8505 Level: developer 8506 8507 .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 8508 @*/ 8509 PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 8510 { 8511 PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8512 PetscErrorCode ierr; 8513 DMPlexInterpolatedFlag interpEnum; 8514 8515 PetscFunctionBegin; 8516 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8517 ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr); 8518 if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 8519 if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 8520 PetscMPIInt rank; 8521 MPI_Comm comm; 8522 8523 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8524 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8525 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 8526 } 8527 8528 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8529 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8530 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8531 for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 8532 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 8533 for (c = cStart; c < cEnd; ++c) { 8534 const PetscInt *cone, *ornt, *faceSizes, *faces; 8535 const DMPolytopeType *faceTypes; 8536 DMPolytopeType ct; 8537 PetscInt numFaces, coneSize, f; 8538 PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 8539 8540 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8541 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8542 if (unsplit) continue; 8543 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8544 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8545 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 8546 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8547 for (cl = 0; cl < closureSize*2; cl += 2) { 8548 const PetscInt p = closure[cl]; 8549 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 8550 } 8551 ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8552 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); 8553 for (f = 0; f < numFaces; ++f) { 8554 DMPolytopeType fct; 8555 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 8556 8557 ierr = DMPlexGetCellType(dm, cone[f], &fct);CHKERRQ(ierr); 8558 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8559 for (cl = 0; cl < fclosureSize*2; cl += 2) { 8560 const PetscInt p = fclosure[cl]; 8561 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 8562 } 8563 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]); 8564 for (v = 0; v < fnumCorners; ++v) { 8565 if (fclosure[v] != faces[fOff+v]) { 8566 PetscInt v1; 8567 8568 ierr = PetscPrintf(PETSC_COMM_SELF, "face closure:");CHKERRQ(ierr); 8569 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", fclosure[v1]);CHKERRQ(ierr);} 8570 ierr = PetscPrintf(PETSC_COMM_SELF, "\ncell face:");CHKERRQ(ierr); 8571 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", faces[fOff+v1]);CHKERRQ(ierr);} 8572 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8573 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]); 8574 } 8575 } 8576 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8577 fOff += faceSizes[f]; 8578 } 8579 ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8580 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8581 } 8582 } 8583 PetscFunctionReturn(0); 8584 } 8585 8586 /*@ 8587 DMPlexCheckGeometry - Check the geometry of mesh cells 8588 8589 Input Parameter: 8590 . dm - The DMPlex object 8591 8592 Notes: 8593 This is a useful diagnostic when creating meshes programmatically. 8594 8595 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8596 8597 Level: developer 8598 8599 .seealso: DMCreate(), DMSetFromOptions() 8600 @*/ 8601 PetscErrorCode DMPlexCheckGeometry(DM dm) 8602 { 8603 Vec coordinates; 8604 PetscReal detJ, J[9], refVol = 1.0; 8605 PetscReal vol; 8606 PetscBool periodic; 8607 PetscInt dim, depth, dE, d, cStart, cEnd, c; 8608 PetscErrorCode ierr; 8609 8610 PetscFunctionBegin; 8611 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8612 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 8613 if (dim != dE) PetscFunctionReturn(0); 8614 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8615 ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr); 8616 for (d = 0; d < dim; ++d) refVol *= 2.0; 8617 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8618 /* Make sure local coordinates are created, because that step is collective */ 8619 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8620 for (c = cStart; c < cEnd; ++c) { 8621 DMPolytopeType ct; 8622 PetscInt unsplit; 8623 PetscBool ignoreZeroVol = PETSC_FALSE; 8624 8625 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8626 switch (ct) { 8627 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8628 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8629 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8630 ignoreZeroVol = PETSC_TRUE; break; 8631 default: break; 8632 } 8633 switch (ct) { 8634 case DM_POLYTOPE_TRI_PRISM: 8635 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8636 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8637 case DM_POLYTOPE_PYRAMID: 8638 continue; 8639 default: break; 8640 } 8641 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8642 if (unsplit) continue; 8643 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 8644 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); 8645 ierr = PetscInfo(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 8646 if (depth > 1 && !periodic) { 8647 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 8648 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); 8649 ierr = PetscInfo(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 8650 } 8651 } 8652 PetscFunctionReturn(0); 8653 } 8654 8655 /*@ 8656 DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 8657 8658 Input Parameters: 8659 . dm - The DMPlex object 8660 8661 Notes: 8662 This is mainly intended for debugging/testing purposes. 8663 It currently checks only meshes with no partition overlapping. 8664 8665 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8666 8667 Level: developer 8668 8669 .seealso: DMGetPointSF(), DMSetFromOptions() 8670 @*/ 8671 PetscErrorCode DMPlexCheckPointSF(DM dm) 8672 { 8673 PetscSF pointSF; 8674 PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 8675 const PetscInt *locals, *rootdegree; 8676 PetscBool distributed; 8677 PetscErrorCode ierr; 8678 8679 PetscFunctionBegin; 8680 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8681 ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr); 8682 ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 8683 if (!distributed) PetscFunctionReturn(0); 8684 ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 8685 if (overlap) { 8686 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping");CHKERRQ(ierr); 8687 PetscFunctionReturn(0); 8688 } 8689 PetscCheckFalse(!pointSF,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 8690 ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr); 8691 PetscCheckFalse(nroots < 0,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 8692 ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 8693 ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 8694 8695 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 8696 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8697 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8698 for (l = 0; l < nleaves; ++l) { 8699 const PetscInt point = locals[l]; 8700 8701 PetscCheckFalse(point >= cStart && point < cEnd,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 8702 } 8703 8704 /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 8705 for (l = 0; l < nleaves; ++l) { 8706 const PetscInt point = locals[l]; 8707 const PetscInt *cone; 8708 PetscInt coneSize, c, idx; 8709 8710 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 8711 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 8712 for (c = 0; c < coneSize; ++c) { 8713 if (!rootdegree[cone[c]]) { 8714 ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr); 8715 PetscCheckFalse(idx < 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 8716 } 8717 } 8718 } 8719 PetscFunctionReturn(0); 8720 } 8721 8722 PetscErrorCode DMPlexCheckAll_Internal(DM dm, PetscInt cellHeight) 8723 { 8724 PetscErrorCode ierr; 8725 8726 PetscFunctionBegin; 8727 ierr = DMPlexCheckSymmetry(dm);CHKERRQ(ierr); 8728 ierr = DMPlexCheckSkeleton(dm, cellHeight);CHKERRQ(ierr); 8729 ierr = DMPlexCheckFaces(dm, cellHeight);CHKERRQ(ierr); 8730 ierr = DMPlexCheckGeometry(dm);CHKERRQ(ierr); 8731 ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr); 8732 ierr = DMPlexCheckInterfaceCones(dm);CHKERRQ(ierr); 8733 PetscFunctionReturn(0); 8734 } 8735 8736 typedef struct cell_stats 8737 { 8738 PetscReal min, max, sum, squaresum; 8739 PetscInt count; 8740 } cell_stats_t; 8741 8742 static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8743 { 8744 PetscInt i, N = *len; 8745 8746 for (i = 0; i < N; i++) { 8747 cell_stats_t *A = (cell_stats_t *) a; 8748 cell_stats_t *B = (cell_stats_t *) b; 8749 8750 B->min = PetscMin(A->min,B->min); 8751 B->max = PetscMax(A->max,B->max); 8752 B->sum += A->sum; 8753 B->squaresum += A->squaresum; 8754 B->count += A->count; 8755 } 8756 } 8757 8758 /*@ 8759 DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8760 8761 Collective on dm 8762 8763 Input Parameters: 8764 + dm - The DMPlex object 8765 . output - If true, statistics will be displayed on stdout 8766 - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8767 8768 Notes: 8769 This is mainly intended for debugging/testing purposes. 8770 8771 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8772 8773 Level: developer 8774 8775 .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality() 8776 @*/ 8777 PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8778 { 8779 DM dmCoarse; 8780 cell_stats_t stats, globalStats; 8781 MPI_Comm comm = PetscObjectComm((PetscObject)dm); 8782 PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 8783 PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8784 PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 8785 PetscMPIInt rank,size; 8786 PetscErrorCode ierr; 8787 8788 PetscFunctionBegin; 8789 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8790 stats.min = PETSC_MAX_REAL; 8791 stats.max = PETSC_MIN_REAL; 8792 stats.sum = stats.squaresum = 0.; 8793 stats.count = 0; 8794 8795 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 8796 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8797 ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr); 8798 ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr); 8799 ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 8800 ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); 8801 for (c = cStart; c < cEnd; c++) { 8802 PetscInt i; 8803 PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8804 8805 ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 8806 PetscCheckFalse(detJ < 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 8807 for (i = 0; i < PetscSqr(cdim); ++i) { 8808 frobJ += J[i] * J[i]; 8809 frobInvJ += invJ[i] * invJ[i]; 8810 } 8811 cond2 = frobJ * frobInvJ; 8812 cond = PetscSqrtReal(cond2); 8813 8814 stats.min = PetscMin(stats.min,cond); 8815 stats.max = PetscMax(stats.max,cond); 8816 stats.sum += cond; 8817 stats.squaresum += cond2; 8818 stats.count++; 8819 if (output && cond > limit) { 8820 PetscSection coordSection; 8821 Vec coordsLocal; 8822 PetscScalar *coords = NULL; 8823 PetscInt Nv, d, clSize, cl, *closure = NULL; 8824 8825 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8826 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8827 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8828 ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr); 8829 for (i = 0; i < Nv/cdim; ++i) { 8830 ierr = PetscSynchronizedPrintf(comm, " Vertex %D: (", i);CHKERRQ(ierr); 8831 for (d = 0; d < cdim; ++d) { 8832 if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);} 8833 ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr); 8834 } 8835 ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr); 8836 } 8837 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8838 for (cl = 0; cl < clSize*2; cl += 2) { 8839 const PetscInt edge = closure[cl]; 8840 8841 if ((edge >= eStart) && (edge < eEnd)) { 8842 PetscReal len; 8843 8844 ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr); 8845 ierr = PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr); 8846 } 8847 } 8848 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8849 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8850 } 8851 } 8852 if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 8853 8854 if (size > 1) { 8855 PetscMPIInt blockLengths[2] = {4,1}; 8856 MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8857 MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8858 MPI_Op statReduce; 8859 8860 ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRMPI(ierr); 8861 ierr = MPI_Type_commit(&statType);CHKERRMPI(ierr); 8862 ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRMPI(ierr); 8863 ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRMPI(ierr); 8864 ierr = MPI_Op_free(&statReduce);CHKERRMPI(ierr); 8865 ierr = MPI_Type_free(&statType);CHKERRMPI(ierr); 8866 } else { 8867 ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr); 8868 } 8869 if (rank == 0) { 8870 count = globalStats.count; 8871 min = globalStats.min; 8872 max = globalStats.max; 8873 mean = globalStats.sum / globalStats.count; 8874 stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8875 } 8876 8877 if (output) { 8878 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); 8879 } 8880 ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 8881 8882 ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 8883 if (dmCoarse) { 8884 PetscBool isplex; 8885 8886 ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 8887 if (isplex) { 8888 ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr); 8889 } 8890 } 8891 PetscFunctionReturn(0); 8892 } 8893 8894 /*@ 8895 DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8896 orthogonal quality below given tolerance. 8897 8898 Collective on dm 8899 8900 Input Parameters: 8901 + dm - The DMPlex object 8902 . fv - Optional PetscFV object for pre-computed cell/face centroid information 8903 - atol - [0, 1] Absolute tolerance for tagging cells. 8904 8905 Output Parameters: 8906 + OrthQual - Vec containing orthogonal quality per cell 8907 - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8908 8909 Options Database Keys: 8910 + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8911 supported. 8912 - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8913 8914 Notes: 8915 Orthogonal quality is given by the following formula: 8916 8917 \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8918 8919 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 8920 is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8921 current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8922 calculating the cosine of the angle between these vectors. 8923 8924 Orthogonal quality ranges from 1 (best) to 0 (worst). 8925 8926 This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8927 pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8928 8929 Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8930 8931 Level: intermediate 8932 8933 .seealso: DMPlexCheckCellShape(), DMCreateLabel() 8934 @*/ 8935 PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8936 { 8937 PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 8938 PetscInt *idx; 8939 PetscScalar *oqVals; 8940 const PetscScalar *cellGeomArr, *faceGeomArr; 8941 PetscReal *ci, *fi, *Ai; 8942 MPI_Comm comm; 8943 Vec cellgeom, facegeom; 8944 DM dmFace, dmCell; 8945 IS glob; 8946 ISLocalToGlobalMapping ltog; 8947 PetscViewer vwr; 8948 PetscErrorCode ierr; 8949 8950 PetscFunctionBegin; 8951 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8952 if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8953 PetscValidPointer(OrthQual, 4); 8954 PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol); 8955 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8956 ierr = DMGetDimension(dm, &nc);CHKERRQ(ierr); 8957 PetscCheckFalse(nc < 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc); 8958 { 8959 DMPlexInterpolatedFlag interpFlag; 8960 8961 ierr = DMPlexIsInterpolated(dm, &interpFlag);CHKERRQ(ierr); 8962 if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 8963 PetscMPIInt rank; 8964 8965 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8966 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 8967 } 8968 } 8969 if (OrthQualLabel) { 8970 PetscValidPointer(OrthQualLabel, 5); 8971 ierr = DMCreateLabel(dm, "Orthogonal_Quality");CHKERRQ(ierr); 8972 ierr = DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel);CHKERRQ(ierr); 8973 } else {*OrthQualLabel = NULL;} 8974 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8975 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8976 ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob);CHKERRQ(ierr); 8977 ierr = ISLocalToGlobalMappingCreateIS(glob, <og);CHKERRQ(ierr); 8978 ierr = ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 8979 ierr = VecCreate(comm, OrthQual);CHKERRQ(ierr); 8980 ierr = VecSetType(*OrthQual, VECSTANDARD);CHKERRQ(ierr); 8981 ierr = VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr); 8982 ierr = VecSetLocalToGlobalMapping(*OrthQual, ltog);CHKERRQ(ierr); 8983 ierr = VecSetUp(*OrthQual);CHKERRQ(ierr); 8984 ierr = ISDestroy(&glob);CHKERRQ(ierr); 8985 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 8986 ierr = DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL);CHKERRQ(ierr); 8987 ierr = VecGetArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8988 ierr = VecGetArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8989 ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr); 8990 ierr = VecGetDM(facegeom, &dmFace);CHKERRQ(ierr); 8991 ierr = PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai);CHKERRQ(ierr); 8992 for (cell = cStart; cell < cEnd; cellIter++,cell++) { 8993 PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 8994 PetscInt cellarr[2], *adj = NULL; 8995 PetscScalar *cArr, *fArr; 8996 PetscReal minvalc = 1.0, minvalf = 1.0; 8997 PetscFVCellGeom *cg; 8998 8999 idx[cellIter] = cell-cStart; 9000 cellarr[0] = cell; 9001 /* Make indexing into cellGeom easier */ 9002 ierr = DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg);CHKERRQ(ierr); 9003 ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj);CHKERRQ(ierr); 9004 /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 9005 ierr = PetscCalloc2(adjSize, &cArr, adjSize, &fArr);CHKERRQ(ierr); 9006 for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 9007 PetscInt i; 9008 const PetscInt neigh = adj[cellneigh]; 9009 PetscReal normci = 0, normfi = 0, normai = 0; 9010 PetscFVCellGeom *cgneigh; 9011 PetscFVFaceGeom *fg; 9012 9013 /* Don't count ourselves in the neighbor list */ 9014 if (neigh == cell) continue; 9015 ierr = DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh);CHKERRQ(ierr); 9016 cellarr[1] = neigh; 9017 { 9018 PetscInt numcovpts; 9019 const PetscInt *covpts; 9020 9021 ierr = DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 9022 ierr = DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg);CHKERRQ(ierr); 9023 ierr = DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 9024 } 9025 9026 /* Compute c_i, f_i and their norms */ 9027 for (i = 0; i < nc; i++) { 9028 ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9029 fi[i] = fg->centroid[i] - cg->centroid[i]; 9030 Ai[i] = fg->normal[i]; 9031 normci += PetscPowReal(ci[i], 2); 9032 normfi += PetscPowReal(fi[i], 2); 9033 normai += PetscPowReal(Ai[i], 2); 9034 } 9035 normci = PetscSqrtReal(normci); 9036 normfi = PetscSqrtReal(normfi); 9037 normai = PetscSqrtReal(normai); 9038 9039 /* Normalize and compute for each face-cell-normal pair */ 9040 for (i = 0; i < nc; i++) { 9041 ci[i] = ci[i]/normci; 9042 fi[i] = fi[i]/normfi; 9043 Ai[i] = Ai[i]/normai; 9044 /* PetscAbs because I don't know if normals are guaranteed to point out */ 9045 cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 9046 fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 9047 } 9048 if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 9049 minvalc = PetscRealPart(cArr[cellneighiter]); 9050 } 9051 if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 9052 minvalf = PetscRealPart(fArr[cellneighiter]); 9053 } 9054 } 9055 ierr = PetscFree(adj);CHKERRQ(ierr); 9056 ierr = PetscFree2(cArr, fArr);CHKERRQ(ierr); 9057 /* Defer to cell if they're equal */ 9058 oqVals[cellIter] = PetscMin(minvalf, minvalc); 9059 if (OrthQualLabel) { 9060 if (PetscRealPart(oqVals[cellIter]) <= atol) {ierr = DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE);CHKERRQ(ierr);} 9061 } 9062 } 9063 ierr = VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES);CHKERRQ(ierr); 9064 ierr = VecAssemblyBegin(*OrthQual);CHKERRQ(ierr); 9065 ierr = VecAssemblyEnd(*OrthQual);CHKERRQ(ierr); 9066 ierr = VecRestoreArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 9067 ierr = VecRestoreArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 9068 ierr = PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL);CHKERRQ(ierr); 9069 if (OrthQualLabel) { 9070 if (vwr) {ierr = DMLabelView(*OrthQualLabel, vwr);CHKERRQ(ierr);} 9071 } 9072 ierr = PetscFree5(idx, oqVals, ci, fi, Ai);CHKERRQ(ierr); 9073 ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr); 9074 ierr = VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view");CHKERRQ(ierr); 9075 PetscFunctionReturn(0); 9076 } 9077 9078 /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 9079 * interpolator construction */ 9080 static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9081 { 9082 PetscSection section, newSection, gsection; 9083 PetscSF sf; 9084 PetscBool hasConstraints, ghasConstraints; 9085 PetscErrorCode ierr; 9086 9087 PetscFunctionBegin; 9088 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9089 PetscValidPointer(odm,2); 9090 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9091 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 9092 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 9093 if (!ghasConstraints) { 9094 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 9095 *odm = dm; 9096 PetscFunctionReturn(0); 9097 } 9098 ierr = DMClone(dm, odm);CHKERRQ(ierr); 9099 ierr = DMCopyFields(dm, *odm);CHKERRQ(ierr); 9100 ierr = DMGetLocalSection(*odm, &newSection);CHKERRQ(ierr); 9101 ierr = DMGetPointSF(*odm, &sf);CHKERRQ(ierr); 9102 ierr = PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 9103 ierr = DMSetGlobalSection(*odm, gsection);CHKERRQ(ierr); 9104 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 9105 PetscFunctionReturn(0); 9106 } 9107 9108 static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9109 { 9110 DM dmco, dmfo; 9111 Mat interpo; 9112 Vec rscale; 9113 Vec cglobalo, clocal; 9114 Vec fglobal, fglobalo, flocal; 9115 PetscBool regular; 9116 PetscErrorCode ierr; 9117 9118 PetscFunctionBegin; 9119 ierr = DMGetFullDM(dmc, &dmco);CHKERRQ(ierr); 9120 ierr = DMGetFullDM(dmf, &dmfo);CHKERRQ(ierr); 9121 ierr = DMSetCoarseDM(dmfo, dmco);CHKERRQ(ierr); 9122 ierr = DMPlexGetRegularRefinement(dmf, ®ular);CHKERRQ(ierr); 9123 ierr = DMPlexSetRegularRefinement(dmfo, regular);CHKERRQ(ierr); 9124 ierr = DMCreateInterpolation(dmco, dmfo, &interpo, &rscale);CHKERRQ(ierr); 9125 ierr = DMCreateGlobalVector(dmco, &cglobalo);CHKERRQ(ierr); 9126 ierr = DMCreateLocalVector(dmc, &clocal);CHKERRQ(ierr); 9127 ierr = VecSet(cglobalo, 0.);CHKERRQ(ierr); 9128 ierr = VecSet(clocal, 0.);CHKERRQ(ierr); 9129 ierr = DMCreateGlobalVector(dmf, &fglobal);CHKERRQ(ierr); 9130 ierr = DMCreateGlobalVector(dmfo, &fglobalo);CHKERRQ(ierr); 9131 ierr = DMCreateLocalVector(dmf, &flocal);CHKERRQ(ierr); 9132 ierr = VecSet(fglobal, 0.);CHKERRQ(ierr); 9133 ierr = VecSet(fglobalo, 0.);CHKERRQ(ierr); 9134 ierr = VecSet(flocal, 0.);CHKERRQ(ierr); 9135 ierr = DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL);CHKERRQ(ierr); 9136 ierr = DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9137 ierr = DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9138 ierr = MatMult(interpo, cglobalo, fglobalo);CHKERRQ(ierr); 9139 ierr = DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9140 ierr = DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9141 ierr = DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9142 ierr = DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9143 *shift = fglobal; 9144 ierr = VecDestroy(&flocal);CHKERRQ(ierr); 9145 ierr = VecDestroy(&fglobalo);CHKERRQ(ierr); 9146 ierr = VecDestroy(&clocal);CHKERRQ(ierr); 9147 ierr = VecDestroy(&cglobalo);CHKERRQ(ierr); 9148 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9149 ierr = MatDestroy(&interpo);CHKERRQ(ierr); 9150 ierr = DMDestroy(&dmfo);CHKERRQ(ierr); 9151 ierr = DMDestroy(&dmco);CHKERRQ(ierr); 9152 PetscFunctionReturn(0); 9153 } 9154 9155 PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9156 { 9157 PetscObject shifto; 9158 Vec shift; 9159 9160 PetscErrorCode ierr; 9161 9162 PetscFunctionBegin; 9163 if (!interp) { 9164 Vec rscale; 9165 9166 ierr = DMCreateInterpolation(coarse, fine, &interp, &rscale);CHKERRQ(ierr); 9167 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9168 } else { 9169 ierr = PetscObjectReference((PetscObject)interp);CHKERRQ(ierr); 9170 } 9171 ierr = PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto);CHKERRQ(ierr); 9172 if (!shifto) { 9173 ierr = DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift);CHKERRQ(ierr); 9174 ierr = PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift);CHKERRQ(ierr); 9175 shifto = (PetscObject) shift; 9176 ierr = VecDestroy(&shift);CHKERRQ(ierr); 9177 } 9178 shift = (Vec) shifto; 9179 ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr); 9180 ierr = VecAXPY(fineSol, 1.0, shift);CHKERRQ(ierr); 9181 ierr = MatDestroy(&interp);CHKERRQ(ierr); 9182 PetscFunctionReturn(0); 9183 } 9184 9185 /* Pointwise interpolation 9186 Just code FEM for now 9187 u^f = I u^c 9188 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 9189 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 9190 I_{ij} = psi^f_i phi^c_j 9191 */ 9192 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9193 { 9194 PetscSection gsc, gsf; 9195 PetscInt m, n; 9196 void *ctx; 9197 DM cdm; 9198 PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9199 PetscErrorCode ierr; 9200 9201 PetscFunctionBegin; 9202 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9203 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9204 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9205 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9206 9207 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 9208 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 9209 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9210 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 9211 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9212 9213 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9214 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9215 if (!isRefined || (regular && cdm == dmCoarse)) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx);CHKERRQ(ierr);} 9216 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 9217 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 9218 if (scaling) { 9219 /* Use naive scaling */ 9220 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 9221 } 9222 PetscFunctionReturn(0); 9223 } 9224 9225 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9226 { 9227 PetscErrorCode ierr; 9228 VecScatter ctx; 9229 9230 PetscFunctionBegin; 9231 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 9232 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 9233 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 9234 PetscFunctionReturn(0); 9235 } 9236 9237 static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9238 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9239 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9240 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 9241 { 9242 const PetscInt Nc = uOff[1] - uOff[0]; 9243 PetscInt c; 9244 for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0; 9245 } 9246 9247 PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9248 { 9249 DM dmc; 9250 PetscDS ds; 9251 Vec ones, locmass; 9252 IS cellIS; 9253 PetscFormKey key; 9254 PetscInt depth; 9255 PetscErrorCode ierr; 9256 9257 PetscFunctionBegin; 9258 ierr = DMClone(dm, &dmc);CHKERRQ(ierr); 9259 ierr = DMCopyDisc(dm, dmc);CHKERRQ(ierr); 9260 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9261 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9262 ierr = DMCreateGlobalVector(dmc, mass);CHKERRQ(ierr); 9263 ierr = DMGetLocalVector(dmc, &ones);CHKERRQ(ierr); 9264 ierr = DMGetLocalVector(dmc, &locmass);CHKERRQ(ierr); 9265 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9266 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9267 ierr = VecSet(locmass, 0.0);CHKERRQ(ierr); 9268 ierr = VecSet(ones, 1.0);CHKERRQ(ierr); 9269 key.label = NULL; 9270 key.value = 0; 9271 key.field = 0; 9272 key.part = 0; 9273 ierr = DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL);CHKERRQ(ierr); 9274 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9275 ierr = VecSet(*mass, 0.0);CHKERRQ(ierr); 9276 ierr = DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass);CHKERRQ(ierr); 9277 ierr = DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass);CHKERRQ(ierr); 9278 ierr = DMRestoreLocalVector(dmc, &ones);CHKERRQ(ierr); 9279 ierr = DMRestoreLocalVector(dmc, &locmass);CHKERRQ(ierr); 9280 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9281 PetscFunctionReturn(0); 9282 } 9283 9284 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9285 { 9286 PetscSection gsc, gsf; 9287 PetscInt m, n; 9288 void *ctx; 9289 DM cdm; 9290 PetscBool regular; 9291 PetscErrorCode ierr; 9292 9293 PetscFunctionBegin; 9294 if (dmFine == dmCoarse) { 9295 DM dmc; 9296 PetscDS ds; 9297 PetscWeakForm wf; 9298 Vec u; 9299 IS cellIS; 9300 PetscFormKey key; 9301 PetscInt depth; 9302 9303 ierr = DMClone(dmFine, &dmc);CHKERRQ(ierr); 9304 ierr = DMCopyDisc(dmFine, dmc);CHKERRQ(ierr); 9305 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9306 ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr); 9307 ierr = PetscWeakFormClear(wf);CHKERRQ(ierr); 9308 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9309 ierr = DMCreateMatrix(dmc, mass);CHKERRQ(ierr); 9310 ierr = DMGetGlobalVector(dmc, &u);CHKERRQ(ierr); 9311 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9312 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9313 ierr = MatZeroEntries(*mass);CHKERRQ(ierr); 9314 key.label = NULL; 9315 key.value = 0; 9316 key.field = 0; 9317 key.part = 0; 9318 ierr = DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL);CHKERRQ(ierr); 9319 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9320 ierr = DMRestoreGlobalVector(dmc, &u);CHKERRQ(ierr); 9321 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9322 } else { 9323 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9324 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9325 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9326 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9327 9328 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 9329 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9330 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 9331 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9332 9333 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9334 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9335 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9336 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9337 } 9338 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 9339 PetscFunctionReturn(0); 9340 } 9341 9342 /*@ 9343 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9344 9345 Input Parameter: 9346 . dm - The DMPlex object 9347 9348 Output Parameter: 9349 . regular - The flag 9350 9351 Level: intermediate 9352 9353 .seealso: DMPlexSetRegularRefinement() 9354 @*/ 9355 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 9356 { 9357 PetscFunctionBegin; 9358 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9359 PetscValidPointer(regular, 2); 9360 *regular = ((DM_Plex *) dm->data)->regularRefinement; 9361 PetscFunctionReturn(0); 9362 } 9363 9364 /*@ 9365 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9366 9367 Input Parameters: 9368 + dm - The DMPlex object 9369 - regular - The flag 9370 9371 Level: intermediate 9372 9373 .seealso: DMPlexGetRegularRefinement() 9374 @*/ 9375 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 9376 { 9377 PetscFunctionBegin; 9378 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9379 ((DM_Plex *) dm->data)->regularRefinement = regular; 9380 PetscFunctionReturn(0); 9381 } 9382 9383 /* anchors */ 9384 /*@ 9385 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9386 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints(). 9387 9388 not collective 9389 9390 Input Parameter: 9391 . dm - The DMPlex object 9392 9393 Output Parameters: 9394 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9395 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9396 9397 Level: intermediate 9398 9399 .seealso: DMPlexSetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints() 9400 @*/ 9401 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9402 { 9403 DM_Plex *plex = (DM_Plex *)dm->data; 9404 PetscErrorCode ierr; 9405 9406 PetscFunctionBegin; 9407 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9408 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 9409 if (anchorSection) *anchorSection = plex->anchorSection; 9410 if (anchorIS) *anchorIS = plex->anchorIS; 9411 PetscFunctionReturn(0); 9412 } 9413 9414 /*@ 9415 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9416 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9417 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9418 9419 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9420 DMGetDefaultConstraints() and filling in the entries in the constraint matrix. 9421 9422 collective on dm 9423 9424 Input Parameters: 9425 + dm - The DMPlex object 9426 . 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). 9427 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9428 9429 The reference counts of anchorSection and anchorIS are incremented. 9430 9431 Level: intermediate 9432 9433 .seealso: DMPlexGetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints() 9434 @*/ 9435 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9436 { 9437 DM_Plex *plex = (DM_Plex *)dm->data; 9438 PetscMPIInt result; 9439 PetscErrorCode ierr; 9440 9441 PetscFunctionBegin; 9442 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9443 if (anchorSection) { 9444 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 9445 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRMPI(ierr); 9446 PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9447 } 9448 if (anchorIS) { 9449 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 9450 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRMPI(ierr); 9451 PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9452 } 9453 9454 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 9455 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 9456 plex->anchorSection = anchorSection; 9457 9458 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 9459 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 9460 plex->anchorIS = anchorIS; 9461 9462 if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9463 PetscInt size, a, pStart, pEnd; 9464 const PetscInt *anchors; 9465 9466 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9467 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 9468 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 9469 for (a = 0; a < size; a++) { 9470 PetscInt p; 9471 9472 p = anchors[a]; 9473 if (p >= pStart && p < pEnd) { 9474 PetscInt dof; 9475 9476 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9477 if (dof) { 9478 PetscErrorCode ierr2; 9479 9480 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 9481 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 9482 } 9483 } 9484 } 9485 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 9486 } 9487 /* reset the generic constraints */ 9488 ierr = DMSetDefaultConstraints(dm,NULL,NULL,NULL);CHKERRQ(ierr); 9489 PetscFunctionReturn(0); 9490 } 9491 9492 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9493 { 9494 PetscSection anchorSection; 9495 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9496 PetscErrorCode ierr; 9497 9498 PetscFunctionBegin; 9499 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9500 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9501 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 9502 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9503 if (numFields) { 9504 PetscInt f; 9505 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 9506 9507 for (f = 0; f < numFields; f++) { 9508 PetscInt numComp; 9509 9510 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 9511 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 9512 } 9513 } 9514 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9515 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9516 pStart = PetscMax(pStart,sStart); 9517 pEnd = PetscMin(pEnd,sEnd); 9518 pEnd = PetscMax(pStart,pEnd); 9519 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 9520 for (p = pStart; p < pEnd; p++) { 9521 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9522 if (dof) { 9523 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 9524 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 9525 for (f = 0; f < numFields; f++) { 9526 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 9527 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 9528 } 9529 } 9530 } 9531 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 9532 ierr = PetscObjectSetName((PetscObject) *cSec, "Constraint Section");CHKERRQ(ierr); 9533 PetscFunctionReturn(0); 9534 } 9535 9536 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9537 { 9538 PetscSection aSec; 9539 PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 9540 const PetscInt *anchors; 9541 PetscInt numFields, f; 9542 IS aIS; 9543 PetscErrorCode ierr; 9544 MatType mtype; 9545 PetscBool iscuda,iskokkos; 9546 9547 PetscFunctionBegin; 9548 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9549 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 9550 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 9551 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 9552 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 9553 ierr = PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr); 9554 if (!iscuda) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr); } 9555 ierr = PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos);CHKERRQ(ierr); 9556 if (!iskokkos) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos);CHKERRQ(ierr); } 9557 if (iscuda) mtype = MATSEQAIJCUSPARSE; 9558 else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9559 else mtype = MATSEQAIJ; 9560 ierr = MatSetType(*cMat,mtype);CHKERRQ(ierr); 9561 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 9562 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 9563 /* cSec will be a subset of aSec and section */ 9564 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 9565 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9566 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 9567 i[0] = 0; 9568 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9569 for (p = pStart; p < pEnd; p++) { 9570 PetscInt rDof, rOff, r; 9571 9572 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9573 if (!rDof) continue; 9574 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9575 if (numFields) { 9576 for (f = 0; f < numFields; f++) { 9577 annz = 0; 9578 for (r = 0; r < rDof; r++) { 9579 a = anchors[rOff + r]; 9580 if (a < sStart || a >= sEnd) continue; 9581 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9582 annz += aDof; 9583 } 9584 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9585 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 9586 for (q = 0; q < dof; q++) { 9587 i[off + q + 1] = i[off + q] + annz; 9588 } 9589 } 9590 } else { 9591 annz = 0; 9592 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9593 for (q = 0; q < dof; q++) { 9594 a = anchors[rOff + q]; 9595 if (a < sStart || a >= sEnd) continue; 9596 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9597 annz += aDof; 9598 } 9599 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9600 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 9601 for (q = 0; q < dof; q++) { 9602 i[off + q + 1] = i[off + q] + annz; 9603 } 9604 } 9605 } 9606 nnz = i[m]; 9607 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 9608 offset = 0; 9609 for (p = pStart; p < pEnd; p++) { 9610 if (numFields) { 9611 for (f = 0; f < numFields; f++) { 9612 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9613 for (q = 0; q < dof; q++) { 9614 PetscInt rDof, rOff, r; 9615 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9616 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9617 for (r = 0; r < rDof; r++) { 9618 PetscInt s; 9619 9620 a = anchors[rOff + r]; 9621 if (a < sStart || a >= sEnd) continue; 9622 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9623 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 9624 for (s = 0; s < aDof; s++) { 9625 j[offset++] = aOff + s; 9626 } 9627 } 9628 } 9629 } 9630 } else { 9631 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9632 for (q = 0; q < dof; q++) { 9633 PetscInt rDof, rOff, r; 9634 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9635 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9636 for (r = 0; r < rDof; r++) { 9637 PetscInt s; 9638 9639 a = anchors[rOff + r]; 9640 if (a < sStart || a >= sEnd) continue; 9641 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9642 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 9643 for (s = 0; s < aDof; s++) { 9644 j[offset++] = aOff + s; 9645 } 9646 } 9647 } 9648 } 9649 } 9650 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 9651 ierr = PetscFree(i);CHKERRQ(ierr); 9652 ierr = PetscFree(j);CHKERRQ(ierr); 9653 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 9654 PetscFunctionReturn(0); 9655 } 9656 9657 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 9658 { 9659 DM_Plex *plex = (DM_Plex *)dm->data; 9660 PetscSection anchorSection, section, cSec; 9661 Mat cMat; 9662 PetscErrorCode ierr; 9663 9664 PetscFunctionBegin; 9665 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9666 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9667 if (anchorSection) { 9668 PetscInt Nf; 9669 9670 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 9671 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 9672 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 9673 ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 9674 if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 9675 ierr = DMSetDefaultConstraints(dm,cSec,cMat,NULL);CHKERRQ(ierr); 9676 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 9677 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 9678 } 9679 PetscFunctionReturn(0); 9680 } 9681 9682 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9683 { 9684 IS subis; 9685 PetscSection section, subsection; 9686 PetscErrorCode ierr; 9687 9688 PetscFunctionBegin; 9689 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9690 PetscCheckFalse(!section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 9691 PetscCheckFalse(!subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9692 /* Create subdomain */ 9693 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 9694 /* Create submodel */ 9695 ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr); 9696 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 9697 ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr); 9698 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 9699 ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 9700 /* Create map from submodel to global model */ 9701 if (is) { 9702 PetscSection sectionGlobal, subsectionGlobal; 9703 IS spIS; 9704 const PetscInt *spmap; 9705 PetscInt *subIndices; 9706 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9707 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9708 9709 ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 9710 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 9711 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 9712 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 9713 ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 9714 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 9715 for (p = pStart; p < pEnd; ++p) { 9716 PetscInt gdof, pSubSize = 0; 9717 9718 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 9719 if (gdof > 0) { 9720 for (f = 0; f < Nf; ++f) { 9721 PetscInt fdof, fcdof; 9722 9723 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 9724 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 9725 pSubSize += fdof-fcdof; 9726 } 9727 subSize += pSubSize; 9728 if (pSubSize) { 9729 if (bs < 0) { 9730 bs = pSubSize; 9731 } else if (bs != pSubSize) { 9732 /* Layout does not admit a pointwise block size */ 9733 bs = 1; 9734 } 9735 } 9736 } 9737 } 9738 /* Must have same blocksize on all procs (some might have no points) */ 9739 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 9740 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 9741 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9742 else {bs = bsMinMax[0];} 9743 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 9744 for (p = pStart; p < pEnd; ++p) { 9745 PetscInt gdof, goff; 9746 9747 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 9748 if (gdof > 0) { 9749 const PetscInt point = spmap[p]; 9750 9751 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 9752 for (f = 0; f < Nf; ++f) { 9753 PetscInt fdof, fcdof, fc, f2, poff = 0; 9754 9755 /* Can get rid of this loop by storing field information in the global section */ 9756 for (f2 = 0; f2 < f; ++f2) { 9757 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 9758 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 9759 poff += fdof-fcdof; 9760 } 9761 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 9762 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 9763 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9764 subIndices[subOff] = goff+poff+fc; 9765 } 9766 } 9767 } 9768 } 9769 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 9770 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 9771 if (bs > 1) { 9772 /* We need to check that the block size does not come from non-contiguous fields */ 9773 PetscInt i, j, set = 1; 9774 for (i = 0; i < subSize; i += bs) { 9775 for (j = 0; j < bs; ++j) { 9776 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9777 } 9778 } 9779 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 9780 } 9781 /* Attach nullspace */ 9782 for (f = 0; f < Nf; ++f) { 9783 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9784 if ((*subdm)->nullspaceConstructors[f]) break; 9785 } 9786 if (f < Nf) { 9787 MatNullSpace nullSpace; 9788 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace);CHKERRQ(ierr); 9789 9790 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 9791 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 9792 } 9793 } 9794 PetscFunctionReturn(0); 9795 } 9796 9797 /*@ 9798 DMPlexMonitorThroughput - Report the cell throughput of FE integration 9799 9800 Input Parameter: 9801 - dm - The DM 9802 9803 Level: developer 9804 9805 Options Database Keys: 9806 . -dm_plex_monitor_throughput - Activate the monitor 9807 9808 .seealso: DMSetFromOptions(), DMPlexCreate() 9809 @*/ 9810 PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9811 { 9812 #if defined(PETSC_USE_LOG) 9813 PetscStageLog stageLog; 9814 PetscLogEvent event; 9815 PetscLogStage stage; 9816 PetscEventPerfInfo eventInfo; 9817 PetscReal cellRate, flopRate; 9818 PetscInt cStart, cEnd, Nf, N; 9819 const char *name; 9820 PetscErrorCode ierr; 9821 #endif 9822 9823 PetscFunctionBegin; 9824 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9825 #if defined(PETSC_USE_LOG) 9826 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 9827 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9828 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9829 ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 9830 ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr); 9831 ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr); 9832 ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr); 9833 N = (cEnd - cStart)*Nf*eventInfo.count; 9834 flopRate = eventInfo.flops/eventInfo.time; 9835 cellRate = N/eventInfo.time; 9836 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); 9837 #else 9838 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9839 #endif 9840 PetscFunctionReturn(0); 9841 } 9842