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 /*@ 144 DMPlexVecView1D - Plot many 1D solutions on the same line graph 145 146 Collective on dm 147 148 Input Parameters: 149 + dm - The DMPlex 150 . n - The number of vectors 151 . u - The array of local vectors 152 - viewer - The Draw viewer 153 154 Level: advanced 155 156 .seealso: VecViewFromOptions(), VecView() 157 @*/ 158 PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer) 159 { 160 PetscDS ds; 161 PetscDraw draw = NULL; 162 PetscDrawLG lg; 163 Vec coordinates; 164 const PetscScalar *coords, **sol; 165 PetscReal *vals; 166 PetscInt *Nc; 167 PetscInt Nf, f, c, Nl, l, i, vStart, vEnd, v; 168 char **names; 169 PetscErrorCode ierr; 170 171 PetscFunctionBegin; 172 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 173 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 174 ierr = PetscDSGetTotalComponents(ds, &Nl);CHKERRQ(ierr); 175 ierr = PetscDSGetComponents(ds, &Nc);CHKERRQ(ierr); 176 177 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 178 if (!draw) PetscFunctionReturn(0); 179 ierr = PetscDrawLGCreate(draw, n*Nl, &lg);CHKERRQ(ierr); 180 181 ierr = PetscMalloc3(n, &sol, n*Nl, &names, n*Nl, &vals);CHKERRQ(ierr); 182 for (i = 0, l = 0; i < n; ++i) { 183 const char *vname; 184 185 ierr = PetscObjectGetName((PetscObject) u[i], &vname);CHKERRQ(ierr); 186 for (f = 0; f < Nf; ++f) { 187 PetscObject disc; 188 const char *fname; 189 char tmpname[PETSC_MAX_PATH_LEN]; 190 191 ierr = PetscDSGetDiscretization(ds, f, &disc);CHKERRQ(ierr); 192 /* TODO Create names for components */ 193 for (c = 0; c < Nc[f]; ++c, ++l) { 194 ierr = PetscObjectGetName(disc, &fname);CHKERRQ(ierr); 195 ierr = PetscStrcpy(tmpname, vname);CHKERRQ(ierr); 196 ierr = PetscStrlcat(tmpname, ":", PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 197 ierr = PetscStrlcat(tmpname, fname, PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 198 ierr = PetscStrallocpy(tmpname, &names[l]);CHKERRQ(ierr); 199 } 200 } 201 } 202 ierr = PetscDrawLGSetLegend(lg, (const char *const *) names);CHKERRQ(ierr); 203 /* Just add P_1 support for now */ 204 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 205 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 206 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 207 for (i = 0; i < n; ++i) {ierr = VecGetArrayRead(u[i], &sol[i]);CHKERRQ(ierr);} 208 for (v = vStart; v < vEnd; ++v) { 209 PetscScalar *x, *svals; 210 211 ierr = DMPlexPointLocalRead(dm, v, coords, &x);CHKERRQ(ierr); 212 for (i = 0; i < n; ++i) { 213 ierr = DMPlexPointLocalRead(dm, v, sol[i], &svals);CHKERRQ(ierr); 214 for (l = 0; l < Nl; ++l) vals[i*Nl + l] = PetscRealPart(svals[l]); 215 } 216 ierr = PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals);CHKERRQ(ierr); 217 } 218 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 219 for (i = 0; i < n; ++i) {ierr = VecRestoreArrayRead(u[i], &sol[i]);CHKERRQ(ierr);} 220 for (l = 0; l < n*Nl; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 221 ierr = PetscFree3(sol, names, vals);CHKERRQ(ierr); 222 223 ierr = PetscDrawLGDraw(lg);CHKERRQ(ierr); 224 ierr = PetscDrawLGDestroy(&lg);CHKERRQ(ierr); 225 PetscFunctionReturn(0); 226 } 227 228 static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer) 229 { 230 DM dm; 231 PetscErrorCode ierr; 232 233 PetscFunctionBegin; 234 ierr = VecGetDM(u, &dm);CHKERRQ(ierr); 235 ierr = DMPlexVecView1D(dm, 1, &u, viewer);CHKERRQ(ierr); 236 PetscFunctionReturn(0); 237 } 238 239 static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer) 240 { 241 DM dm; 242 PetscSection s; 243 PetscDraw draw, popup; 244 DM cdm; 245 PetscSection coordSection; 246 Vec coordinates; 247 const PetscScalar *coords, *array; 248 PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 249 PetscReal vbound[2], time; 250 PetscBool flg; 251 PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 252 const char *name; 253 char title[PETSC_MAX_PATH_LEN]; 254 PetscErrorCode ierr; 255 256 PetscFunctionBegin; 257 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 258 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 259 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 260 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 261 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 262 ierr = DMGetCoarsenLevel(dm, &level);CHKERRQ(ierr); 263 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 264 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 265 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 266 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 267 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 268 269 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 270 ierr = DMGetOutputSequenceNumber(dm, &step, &time);CHKERRQ(ierr); 271 272 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 273 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 274 for (c = 0; c < N; c += dim) { 275 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 276 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 277 } 278 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 279 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 280 281 /* Could implement something like DMDASelectFields() */ 282 for (f = 0; f < Nf; ++f) { 283 DM fdm = dm; 284 Vec fv = v; 285 IS fis; 286 char prefix[PETSC_MAX_PATH_LEN]; 287 const char *fname; 288 289 ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr); 290 ierr = PetscSectionGetFieldName(s, f, &fname);CHKERRQ(ierr); 291 292 if (v->hdr.prefix) {ierr = PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix));CHKERRQ(ierr);} 293 else {prefix[0] = '\0';} 294 if (Nf > 1) { 295 ierr = DMCreateSubDM(dm, 1, &f, &fis, &fdm);CHKERRQ(ierr); 296 ierr = VecGetSubVector(v, fis, &fv);CHKERRQ(ierr); 297 ierr = PetscStrlcat(prefix, fname,sizeof(prefix));CHKERRQ(ierr); 298 ierr = PetscStrlcat(prefix, "_",sizeof(prefix));CHKERRQ(ierr); 299 } 300 for (comp = 0; comp < Nc; ++comp, ++w) { 301 PetscInt nmax = 2; 302 303 ierr = PetscViewerDrawGetDraw(viewer, w, &draw);CHKERRQ(ierr); 304 if (Nc > 1) {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time);CHKERRQ(ierr);} 305 else {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time);CHKERRQ(ierr);} 306 ierr = PetscDrawSetTitle(draw, title);CHKERRQ(ierr); 307 308 /* TODO Get max and min only for this component */ 309 ierr = PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg);CHKERRQ(ierr); 310 if (!flg) { 311 ierr = VecMin(fv, NULL, &vbound[0]);CHKERRQ(ierr); 312 ierr = VecMax(fv, NULL, &vbound[1]);CHKERRQ(ierr); 313 if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 314 } 315 ierr = PetscDrawGetPopup(draw, &popup);CHKERRQ(ierr); 316 ierr = PetscDrawScalePopup(popup, vbound[0], vbound[1]);CHKERRQ(ierr); 317 ierr = PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]);CHKERRQ(ierr); 318 319 ierr = VecGetArrayRead(fv, &array);CHKERRQ(ierr); 320 for (c = cStart; c < cEnd; ++c) { 321 PetscScalar *coords = NULL, *a = NULL; 322 PetscInt numCoords, color[4] = {-1,-1,-1,-1}; 323 324 ierr = DMPlexPointLocalRead(fdm, c, array, &a);CHKERRQ(ierr); 325 if (a) { 326 color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 327 color[1] = color[2] = color[3] = color[0]; 328 } else { 329 PetscScalar *vals = NULL; 330 PetscInt numVals, va; 331 332 ierr = DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 333 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); 334 switch (numVals/Nc) { 335 case 3: /* P1 Triangle */ 336 case 4: /* P1 Quadrangle */ 337 for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]); 338 break; 339 case 6: /* P2 Triangle */ 340 case 8: /* P2 Quadrangle */ 341 for (va = 0; va < numVals/(Nc*2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp + numVals/(Nc*2)]), vbound[0], vbound[1]); 342 break; 343 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc); 344 } 345 ierr = DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 346 } 347 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 348 switch (numCoords) { 349 case 6: 350 case 12: /* Localized triangle */ 351 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); 352 break; 353 case 8: 354 case 16: /* Localized quadrilateral */ 355 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); 356 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); 357 break; 358 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords); 359 } 360 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 361 } 362 ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr); 363 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 364 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 365 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 366 } 367 if (Nf > 1) { 368 ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr); 369 ierr = ISDestroy(&fis);CHKERRQ(ierr); 370 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 371 } 372 } 373 PetscFunctionReturn(0); 374 } 375 376 static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 377 { 378 DM dm; 379 PetscDraw draw; 380 PetscInt dim; 381 PetscBool isnull; 382 PetscErrorCode ierr; 383 384 PetscFunctionBegin; 385 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 386 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 387 if (isnull) PetscFunctionReturn(0); 388 389 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 390 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 391 switch (dim) { 392 case 1: VecView_Plex_Local_Draw_1D(v, viewer);CHKERRQ(ierr);break; 393 case 2: VecView_Plex_Local_Draw_2D(v, viewer);CHKERRQ(ierr);break; 394 default: SETERRQ(PetscObjectComm((PetscObject) v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D. Try PETSCVIEWERGLVIS", dim); 395 } 396 PetscFunctionReturn(0); 397 } 398 399 static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 400 { 401 DM dm; 402 Vec locv; 403 const char *name; 404 PetscSection section; 405 PetscInt pStart, pEnd; 406 PetscInt numFields; 407 PetscViewerVTKFieldType ft; 408 PetscErrorCode ierr; 409 410 PetscFunctionBegin; 411 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 412 ierr = DMCreateLocalVector(dm, &locv);CHKERRQ(ierr); /* VTK viewer requires exclusive ownership of the vector */ 413 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 414 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 415 ierr = VecCopy(v, locv);CHKERRQ(ierr); 416 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 417 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 418 if (!numFields) { 419 ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 420 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 421 } else { 422 PetscInt f; 423 424 for (f = 0; f < numFields; f++) { 425 ierr = DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft);CHKERRQ(ierr); 426 if (ft == PETSC_VTK_INVALID) continue; 427 ierr = PetscObjectReference((PetscObject)locv);CHKERRQ(ierr); 428 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 429 } 430 ierr = VecDestroy(&locv);CHKERRQ(ierr); 431 } 432 PetscFunctionReturn(0); 433 } 434 435 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 436 { 437 DM dm; 438 PetscBool isvtk, ishdf5, isdraw, isglvis; 439 PetscErrorCode ierr; 440 441 PetscFunctionBegin; 442 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 443 PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 444 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 445 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 446 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 447 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 448 if (isvtk || ishdf5 || isdraw || isglvis) { 449 PetscInt i,numFields; 450 PetscObject fe; 451 PetscBool fem = PETSC_FALSE; 452 Vec locv = v; 453 const char *name; 454 PetscInt step; 455 PetscReal time; 456 457 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 458 for (i=0; i<numFields; i++) { 459 ierr = DMGetField(dm, i, NULL, &fe);CHKERRQ(ierr); 460 if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; } 461 } 462 if (fem) { 463 PetscObject isZero; 464 465 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 466 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 467 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 468 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 469 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 470 ierr = VecCopy(v, locv);CHKERRQ(ierr); 471 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 472 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr); 473 } 474 if (isvtk) { 475 ierr = VecView_Plex_Local_VTK(locv, viewer);CHKERRQ(ierr); 476 } else if (ishdf5) { 477 #if defined(PETSC_HAVE_HDF5) 478 ierr = VecView_Plex_Local_HDF5_Internal(locv, viewer);CHKERRQ(ierr); 479 #else 480 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 481 #endif 482 } else if (isdraw) { 483 ierr = VecView_Plex_Local_Draw(locv, viewer);CHKERRQ(ierr); 484 } else if (isglvis) { 485 ierr = DMGetOutputSequenceNumber(dm, &step, NULL);CHKERRQ(ierr); 486 ierr = PetscViewerGLVisSetSnapId(viewer, step);CHKERRQ(ierr); 487 ierr = VecView_GLVis(locv, viewer);CHKERRQ(ierr); 488 } 489 if (fem) { 490 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 491 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 492 } 493 } else { 494 PetscBool isseq; 495 496 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 497 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 498 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 499 } 500 PetscFunctionReturn(0); 501 } 502 503 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 504 { 505 DM dm; 506 PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii; 507 PetscErrorCode ierr; 508 509 PetscFunctionBegin; 510 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 511 PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 512 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 513 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 514 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 515 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 516 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 517 if (isvtk || isdraw || isglvis) { 518 Vec locv; 519 PetscObject isZero; 520 const char *name; 521 522 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 523 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 524 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 525 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 526 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 527 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 528 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 529 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 530 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 531 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 532 } else if (ishdf5) { 533 #if defined(PETSC_HAVE_HDF5) 534 ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 535 #else 536 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 537 #endif 538 } else if (isexodusii) { 539 #if defined(PETSC_HAVE_EXODUSII) 540 ierr = VecView_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 541 #else 542 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 543 #endif 544 } else { 545 PetscBool isseq; 546 547 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 548 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 549 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 550 } 551 PetscFunctionReturn(0); 552 } 553 554 PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 555 { 556 DM dm; 557 MPI_Comm comm; 558 PetscViewerFormat format; 559 Vec v; 560 PetscBool isvtk, ishdf5; 561 PetscErrorCode ierr; 562 563 PetscFunctionBegin; 564 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 565 ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 566 PetscCheckFalse(!dm,comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 567 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 568 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 569 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 570 if (format == PETSC_VIEWER_NATIVE) { 571 /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 572 /* this need a better fix */ 573 if (dm->useNatural) { 574 if (dm->sfNatural) { 575 const char *vecname; 576 PetscInt n, nroots; 577 578 ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr); 579 ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 580 if (n == nroots) { 581 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 582 ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 583 ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 584 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 585 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 586 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 587 } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 588 } else v = originalv; 589 } else v = originalv; 590 591 if (ishdf5) { 592 #if defined(PETSC_HAVE_HDF5) 593 ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 594 #else 595 SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 596 #endif 597 } else if (isvtk) { 598 SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 599 } else { 600 PetscBool isseq; 601 602 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 603 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 604 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 605 } 606 if (v != originalv) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 607 PetscFunctionReturn(0); 608 } 609 610 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 611 { 612 DM dm; 613 PetscBool ishdf5; 614 PetscErrorCode ierr; 615 616 PetscFunctionBegin; 617 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 618 PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 619 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 620 if (ishdf5) { 621 DM dmBC; 622 Vec gv; 623 const char *name; 624 625 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 626 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 627 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 628 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 629 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 630 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 631 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 632 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 633 } else { 634 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 635 } 636 PetscFunctionReturn(0); 637 } 638 639 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 640 { 641 DM dm; 642 PetscBool ishdf5,isexodusii; 643 PetscErrorCode ierr; 644 645 PetscFunctionBegin; 646 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 647 PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 648 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 649 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 650 if (ishdf5) { 651 #if defined(PETSC_HAVE_HDF5) 652 ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 653 #else 654 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 655 #endif 656 } else if (isexodusii) { 657 #if defined(PETSC_HAVE_EXODUSII) 658 ierr = VecLoad_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 659 #else 660 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 661 #endif 662 } else { 663 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 664 } 665 PetscFunctionReturn(0); 666 } 667 668 PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 669 { 670 DM dm; 671 PetscViewerFormat format; 672 PetscBool ishdf5; 673 PetscErrorCode ierr; 674 675 PetscFunctionBegin; 676 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 677 PetscCheckFalse(!dm,PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 678 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 679 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 680 if (format == PETSC_VIEWER_NATIVE) { 681 if (dm->useNatural) { 682 if (dm->sfNatural) { 683 if (ishdf5) { 684 #if defined(PETSC_HAVE_HDF5) 685 Vec v; 686 const char *vecname; 687 688 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 689 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 690 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 691 ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 692 ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 693 ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 694 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 695 #else 696 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 697 #endif 698 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 699 } 700 } else { 701 ierr = VecLoad_Default(originalv, viewer);CHKERRQ(ierr); 702 } 703 } 704 PetscFunctionReturn(0); 705 } 706 707 PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 708 { 709 PetscSection coordSection; 710 Vec coordinates; 711 DMLabel depthLabel, celltypeLabel; 712 const char *name[4]; 713 const PetscScalar *a; 714 PetscInt dim, pStart, pEnd, cStart, cEnd, c; 715 PetscErrorCode ierr; 716 717 PetscFunctionBegin; 718 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 719 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 720 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 721 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 722 ierr = DMPlexGetCellTypeLabel(dm, &celltypeLabel);CHKERRQ(ierr); 723 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 724 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 725 ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 726 name[0] = "vertex"; 727 name[1] = "edge"; 728 name[dim-1] = "face"; 729 name[dim] = "cell"; 730 for (c = cStart; c < cEnd; ++c) { 731 PetscInt *closure = NULL; 732 PetscInt closureSize, cl, ct; 733 734 ierr = DMLabelGetValue(celltypeLabel, c, &ct);CHKERRQ(ierr); 735 ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]);CHKERRQ(ierr); 736 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 737 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 738 for (cl = 0; cl < closureSize*2; cl += 2) { 739 PetscInt point = closure[cl], depth, dof, off, d, p; 740 741 if ((point < pStart) || (point >= pEnd)) continue; 742 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 743 if (!dof) continue; 744 ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 745 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 746 ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr); 747 for (p = 0; p < dof/dim; ++p) { 748 ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 749 for (d = 0; d < dim; ++d) { 750 if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 751 ierr = PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 752 } 753 ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 754 } 755 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 756 } 757 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 758 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 759 } 760 ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 761 PetscFunctionReturn(0); 762 } 763 764 typedef enum {CS_CARTESIAN, CS_POLAR, CS_CYLINDRICAL, CS_SPHERICAL} CoordSystem; 765 const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 766 767 static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 768 { 769 PetscInt i; 770 PetscErrorCode ierr; 771 772 PetscFunctionBegin; 773 if (dim > 3) { 774 for (i = 0; i < dim; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) PetscRealPart(x[i]));CHKERRQ(ierr);} 775 } else { 776 PetscReal coords[3], trcoords[3]; 777 778 for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 779 switch (cs) { 780 case CS_CARTESIAN: for (i = 0; i < dim; ++i) trcoords[i] = coords[i];break; 781 case CS_POLAR: 782 PetscCheckFalse(dim != 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %D", dim); 783 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 784 trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 785 break; 786 case CS_CYLINDRICAL: 787 PetscCheckFalse(dim != 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %D", dim); 788 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 789 trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 790 trcoords[2] = coords[2]; 791 break; 792 case CS_SPHERICAL: 793 PetscCheckFalse(dim != 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %D", dim); 794 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 795 trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 796 trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 797 break; 798 } 799 for (i = 0; i < dim; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) trcoords[i]);CHKERRQ(ierr);} 800 } 801 PetscFunctionReturn(0); 802 } 803 804 static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 805 { 806 DM_Plex *mesh = (DM_Plex*) dm->data; 807 DM cdm; 808 PetscSection coordSection; 809 Vec coordinates; 810 PetscViewerFormat format; 811 PetscErrorCode ierr; 812 813 PetscFunctionBegin; 814 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 815 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 816 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 817 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 818 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 819 const char *name; 820 PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 821 PetscInt pStart, pEnd, p, numLabels, l; 822 PetscMPIInt rank, size; 823 824 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 825 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 826 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 827 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 828 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 829 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 830 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 831 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 832 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 833 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 834 ierr = PetscViewerASCIIPrintf(viewer, "Supports:\n", name);CHKERRQ(ierr); 835 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 836 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize);CHKERRQ(ierr); 837 for (p = pStart; p < pEnd; ++p) { 838 PetscInt dof, off, s; 839 840 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 841 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 842 for (s = off; s < off+dof; ++s) { 843 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 844 } 845 } 846 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 847 ierr = PetscViewerASCIIPrintf(viewer, "Cones:\n", name);CHKERRQ(ierr); 848 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize);CHKERRQ(ierr); 849 for (p = pStart; p < pEnd; ++p) { 850 PetscInt dof, off, c; 851 852 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 853 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 854 for (c = off; c < off+dof; ++c) { 855 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 856 } 857 } 858 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 859 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 860 if (coordSection && coordinates) { 861 CoordSystem cs = CS_CARTESIAN; 862 const PetscScalar *array; 863 PetscInt Nf, Nc, pStart, pEnd, p; 864 PetscMPIInt rank; 865 const char *name; 866 867 ierr = PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL);CHKERRQ(ierr); 868 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRMPI(ierr); 869 ierr = PetscSectionGetNumFields(coordSection, &Nf);CHKERRQ(ierr); 870 PetscCheckFalse(Nf != 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %D", Nf); 871 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 872 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 873 ierr = PetscObjectGetName((PetscObject) coordinates, &name);CHKERRQ(ierr); 874 ierr = PetscViewerASCIIPrintf(viewer, "%s with %D fields\n", name, Nf);CHKERRQ(ierr); 875 ierr = PetscViewerASCIIPrintf(viewer, " field 0 with %D components\n", Nc);CHKERRQ(ierr); 876 if (cs != CS_CARTESIAN) {ierr = PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs]);CHKERRQ(ierr);} 877 878 ierr = VecGetArrayRead(coordinates, &array);CHKERRQ(ierr); 879 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 880 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank);CHKERRQ(ierr); 881 for (p = pStart; p < pEnd; ++p) { 882 PetscInt dof, off; 883 884 ierr = PetscSectionGetDof(coordSection, p, &dof);CHKERRQ(ierr); 885 ierr = PetscSectionGetOffset(coordSection, p, &off);CHKERRQ(ierr); 886 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " (%4D) dim %2D offset %3D", p, dof, off);CHKERRQ(ierr); 887 ierr = DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]);CHKERRQ(ierr); 888 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\n");CHKERRQ(ierr); 889 } 890 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 891 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 892 ierr = VecRestoreArrayRead(coordinates, &array);CHKERRQ(ierr); 893 } 894 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 895 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 896 for (l = 0; l < numLabels; ++l) { 897 DMLabel label; 898 PetscBool isdepth; 899 const char *name; 900 901 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 902 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 903 if (isdepth) continue; 904 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 905 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 906 } 907 if (size > 1) { 908 PetscSF sf; 909 910 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 911 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 912 } 913 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 914 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 915 const char *name, *color; 916 const char *defcolors[3] = {"gray", "orange", "green"}; 917 const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 918 char lname[PETSC_MAX_PATH_LEN]; 919 PetscReal scale = 2.0; 920 PetscReal tikzscale = 1.0; 921 PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 922 double tcoords[3]; 923 PetscScalar *coords; 924 PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 925 PetscMPIInt rank, size; 926 char **names, **colors, **lcolors; 927 PetscBool flg, lflg; 928 PetscBT wp = NULL; 929 PetscInt pEnd, pStart; 930 931 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 932 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 933 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 934 numLabels = PetscMax(numLabels, 10); 935 numColors = 10; 936 numLColors = 10; 937 ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 938 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 939 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL);CHKERRQ(ierr); 940 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 941 for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 942 for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 943 n = 4; 944 ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg);CHKERRQ(ierr); 945 PetscCheckFalse(flg && n != dim+1,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 946 ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg);CHKERRQ(ierr); 947 PetscCheckFalse(flg && n != dim+1,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 948 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 949 if (!useLabels) numLabels = 0; 950 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 951 if (!useColors) { 952 numColors = 3; 953 for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 954 } 955 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 956 if (!useColors) { 957 numLColors = 4; 958 for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 959 } 960 ierr = PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg);CHKERRQ(ierr); 961 plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 962 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg);CHKERRQ(ierr); 963 PetscCheckFalse(flg && plotEdges && depth < dim,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 964 if (depth < dim) plotEdges = PETSC_FALSE; 965 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL);CHKERRQ(ierr); 966 967 /* filter points with labelvalue != labeldefaultvalue */ 968 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 969 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 970 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 971 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 972 if (lflg) { 973 DMLabel lbl; 974 975 ierr = DMGetLabel(dm, lname, &lbl);CHKERRQ(ierr); 976 if (lbl) { 977 PetscInt val, defval; 978 979 ierr = DMLabelGetDefaultValue(lbl, &defval);CHKERRQ(ierr); 980 ierr = PetscBTCreate(pEnd-pStart, &wp);CHKERRQ(ierr); 981 for (c = pStart; c < pEnd; c++) { 982 PetscInt *closure = NULL; 983 PetscInt closureSize; 984 985 ierr = DMLabelGetValue(lbl, c, &val);CHKERRQ(ierr); 986 if (val == defval) continue; 987 988 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 989 for (p = 0; p < closureSize*2; p += 2) { 990 ierr = PetscBTSet(wp, closure[p] - pStart);CHKERRQ(ierr); 991 } 992 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 993 } 994 } 995 } 996 997 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 998 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 999 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 1000 ierr = PetscViewerASCIIPrintf(viewer, "\ 1001 \\documentclass[tikz]{standalone}\n\n\ 1002 \\usepackage{pgflibraryshapes}\n\ 1003 \\usetikzlibrary{backgrounds}\n\ 1004 \\usetikzlibrary{arrows}\n\ 1005 \\begin{document}\n");CHKERRQ(ierr); 1006 if (size > 1) { 1007 ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 1008 for (p = 0; p < size; ++p) { 1009 if (p > 0 && p == size-1) { 1010 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 1011 } else if (p > 0) { 1012 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 1013 } 1014 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 1015 } 1016 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 1017 } 1018 if (drawHasse) { 1019 PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart)); 1020 1021 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%D}\n", vStart);CHKERRQ(ierr); 1022 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%D}\n", vEnd-1);CHKERRQ(ierr); 1023 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%D}\n", vEnd-vStart);CHKERRQ(ierr); 1024 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.);CHKERRQ(ierr); 1025 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%D}\n", eStart);CHKERRQ(ierr); 1026 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%D}\n", eEnd-1);CHKERRQ(ierr); 1027 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.);CHKERRQ(ierr); 1028 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%D}\n", eEnd-eStart);CHKERRQ(ierr); 1029 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%D}\n", cStart);CHKERRQ(ierr); 1030 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%D}\n", cEnd-1);CHKERRQ(ierr); 1031 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%D}\n", cEnd-cStart);CHKERRQ(ierr); 1032 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.);CHKERRQ(ierr); 1033 } 1034 ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale);CHKERRQ(ierr); 1035 1036 /* Plot vertices */ 1037 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1038 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 1039 for (v = vStart; v < vEnd; ++v) { 1040 PetscInt off, dof, d; 1041 PetscBool isLabeled = PETSC_FALSE; 1042 1043 if (wp && !PetscBTLookup(wp,v - pStart)) continue; 1044 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 1045 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 1046 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 1047 PetscCheckFalse(dof > 3,PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 1048 for (d = 0; d < dof; ++d) { 1049 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1050 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1051 } 1052 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1053 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1054 for (d = 0; d < dof; ++d) { 1055 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 1056 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]);CHKERRQ(ierr); 1057 } 1058 if (drawHasse) color = colors[0%numColors]; 1059 else color = colors[rank%numColors]; 1060 for (l = 0; l < numLabels; ++l) { 1061 PetscInt val; 1062 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 1063 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 1064 } 1065 if (drawNumbers[0]) { 1066 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 1067 } else if (drawColors[0]) { 1068 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 1069 } else { 1070 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", v, rank);CHKERRQ(ierr); 1071 } 1072 } 1073 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1074 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1075 /* Plot edges */ 1076 if (plotEdges) { 1077 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1078 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 1079 for (e = eStart; e < eEnd; ++e) { 1080 const PetscInt *cone; 1081 PetscInt coneSize, offA, offB, dof, d; 1082 1083 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 1084 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 1085 PetscCheckFalse(coneSize != 2,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 1086 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 1087 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 1088 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 1089 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 1090 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 1091 for (d = 0; d < dof; ++d) { 1092 tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 1093 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1094 } 1095 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1096 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1097 for (d = 0; d < dof; ++d) { 1098 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 1099 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr); 1100 } 1101 if (drawHasse) color = colors[1%numColors]; 1102 else color = colors[rank%numColors]; 1103 for (l = 0; l < numLabels; ++l) { 1104 PetscInt val; 1105 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 1106 if (val >= 0) {color = lcolors[l%numLColors]; break;} 1107 } 1108 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 1109 } 1110 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1111 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1112 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 1113 } 1114 /* Plot cells */ 1115 if (dim == 3 || !drawNumbers[1]) { 1116 for (e = eStart; e < eEnd; ++e) { 1117 const PetscInt *cone; 1118 1119 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 1120 color = colors[rank%numColors]; 1121 for (l = 0; l < numLabels; ++l) { 1122 PetscInt val; 1123 ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 1124 if (val >= 0) {color = lcolors[l%numLColors]; break;} 1125 } 1126 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 1127 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 1128 } 1129 } else { 1130 DMPolytopeType ct; 1131 1132 /* Drawing a 2D polygon */ 1133 for (c = cStart; c < cEnd; ++c) { 1134 if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1135 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 1136 if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || 1137 ct == DM_POLYTOPE_TRI_PRISM_TENSOR || 1138 ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 1139 const PetscInt *cone; 1140 PetscInt coneSize, e; 1141 1142 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 1143 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 1144 for (e = 0; e < coneSize; ++e) { 1145 const PetscInt *econe; 1146 1147 ierr = DMPlexGetCone(dm, cone[e], &econe);CHKERRQ(ierr); 1148 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); 1149 } 1150 } else { 1151 PetscInt *closure = NULL; 1152 PetscInt closureSize, Nv = 0, v; 1153 1154 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1155 for (p = 0; p < closureSize*2; p += 2) { 1156 const PetscInt point = closure[p]; 1157 1158 if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1159 } 1160 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 1161 for (v = 0; v <= Nv; ++v) { 1162 const PetscInt vertex = closure[v%Nv]; 1163 1164 if (v > 0) { 1165 if (plotEdges) { 1166 const PetscInt *edge; 1167 PetscInt endpoints[2], ne; 1168 1169 endpoints[0] = closure[v-1]; endpoints[1] = vertex; 1170 ierr = DMPlexGetJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr); 1171 PetscCheckFalse(ne != 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %D, %D", endpoints[0], endpoints[1]); 1172 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d) -- ", edge[0], rank);CHKERRQ(ierr); 1173 ierr = DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr); 1174 } else { 1175 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr); 1176 } 1177 } 1178 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", vertex, rank);CHKERRQ(ierr); 1179 } 1180 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ";\n");CHKERRQ(ierr); 1181 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1182 } 1183 } 1184 } 1185 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1186 for (c = cStart; c < cEnd; ++c) { 1187 double ccoords[3] = {0.0, 0.0, 0.0}; 1188 PetscBool isLabeled = PETSC_FALSE; 1189 PetscInt *closure = NULL; 1190 PetscInt closureSize, dof, d, n = 0; 1191 1192 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 1193 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1194 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 1195 for (p = 0; p < closureSize*2; p += 2) { 1196 const PetscInt point = closure[p]; 1197 PetscInt off; 1198 1199 if ((point < vStart) || (point >= vEnd)) continue; 1200 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 1201 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 1202 for (d = 0; d < dof; ++d) { 1203 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1204 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1205 } 1206 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1207 if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1208 for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 1209 ++n; 1210 } 1211 for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 1212 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1213 for (d = 0; d < dof; ++d) { 1214 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 1215 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]);CHKERRQ(ierr); 1216 } 1217 if (drawHasse) color = colors[depth%numColors]; 1218 else color = colors[rank%numColors]; 1219 for (l = 0; l < numLabels; ++l) { 1220 PetscInt val; 1221 ierr = DMGetLabelValue(dm, names[l], c, &val);CHKERRQ(ierr); 1222 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 1223 } 1224 if (drawNumbers[dim]) { 1225 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c);CHKERRQ(ierr); 1226 } else if (drawColors[dim]) { 1227 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 1228 } else { 1229 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", c, rank);CHKERRQ(ierr); 1230 } 1231 } 1232 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1233 if (drawHasse) { 1234 color = colors[depth%numColors]; 1235 ierr = PetscViewerASCIIPrintf(viewer, "%% Cells\n");CHKERRQ(ierr); 1236 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n");CHKERRQ(ierr); 1237 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1238 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); 1239 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1240 1241 color = colors[1%numColors]; 1242 ierr = PetscViewerASCIIPrintf(viewer, "%% Edges\n");CHKERRQ(ierr); 1243 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n");CHKERRQ(ierr); 1244 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1245 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); 1246 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1247 1248 color = colors[0%numColors]; 1249 ierr = PetscViewerASCIIPrintf(viewer, "%% Vertices\n");CHKERRQ(ierr); 1250 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n");CHKERRQ(ierr); 1251 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1252 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); 1253 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1254 1255 for (p = pStart; p < pEnd; ++p) { 1256 const PetscInt *cone; 1257 PetscInt coneSize, cp; 1258 1259 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1260 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1261 for (cp = 0; cp < coneSize; ++cp) { 1262 ierr = PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%D_%d) -- (%D_%d);\n", cone[cp], rank, p, rank);CHKERRQ(ierr); 1263 } 1264 } 1265 } 1266 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1267 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 1268 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 1269 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 1270 for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 1271 for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 1272 for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 1273 ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 1274 ierr = PetscBTDestroy(&wp);CHKERRQ(ierr); 1275 } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 1276 Vec cown,acown; 1277 VecScatter sct; 1278 ISLocalToGlobalMapping g2l; 1279 IS gid,acis; 1280 MPI_Comm comm,ncomm = MPI_COMM_NULL; 1281 MPI_Group ggroup,ngroup; 1282 PetscScalar *array,nid; 1283 const PetscInt *idxs; 1284 PetscInt *idxs2,*start,*adjacency,*work; 1285 PetscInt64 lm[3],gm[3]; 1286 PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 1287 PetscMPIInt d1,d2,rank; 1288 1289 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1290 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 1291 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1292 ierr = MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm);CHKERRMPI(ierr); 1293 #endif 1294 if (ncomm != MPI_COMM_NULL) { 1295 ierr = MPI_Comm_group(comm,&ggroup);CHKERRMPI(ierr); 1296 ierr = MPI_Comm_group(ncomm,&ngroup);CHKERRMPI(ierr); 1297 d1 = 0; 1298 ierr = MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2);CHKERRMPI(ierr); 1299 nid = d2; 1300 ierr = MPI_Group_free(&ggroup);CHKERRMPI(ierr); 1301 ierr = MPI_Group_free(&ngroup);CHKERRMPI(ierr); 1302 ierr = MPI_Comm_free(&ncomm);CHKERRMPI(ierr); 1303 } else nid = 0.0; 1304 1305 /* Get connectivity */ 1306 ierr = DMPlexGetVTKCellHeight(dm,&cellHeight);CHKERRQ(ierr); 1307 ierr = DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid);CHKERRQ(ierr); 1308 1309 /* filter overlapped local cells */ 1310 ierr = DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd);CHKERRQ(ierr); 1311 ierr = ISGetIndices(gid,&idxs);CHKERRQ(ierr); 1312 ierr = ISGetLocalSize(gid,&cum);CHKERRQ(ierr); 1313 ierr = PetscMalloc1(cum,&idxs2);CHKERRQ(ierr); 1314 for (c = cStart, cum = 0; c < cEnd; c++) { 1315 if (idxs[c-cStart] < 0) continue; 1316 idxs2[cum++] = idxs[c-cStart]; 1317 } 1318 ierr = ISRestoreIndices(gid,&idxs);CHKERRQ(ierr); 1319 PetscCheckFalse(numVertices != cum,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum); 1320 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1321 ierr = ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid);CHKERRQ(ierr); 1322 1323 /* support for node-aware cell locality */ 1324 ierr = ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis);CHKERRQ(ierr); 1325 ierr = VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown);CHKERRQ(ierr); 1326 ierr = VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown);CHKERRQ(ierr); 1327 ierr = VecGetArray(cown,&array);CHKERRQ(ierr); 1328 for (c = 0; c < numVertices; c++) array[c] = nid; 1329 ierr = VecRestoreArray(cown,&array);CHKERRQ(ierr); 1330 ierr = VecScatterCreate(cown,acis,acown,NULL,&sct);CHKERRQ(ierr); 1331 ierr = VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1332 ierr = VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1333 ierr = ISDestroy(&acis);CHKERRQ(ierr); 1334 ierr = VecScatterDestroy(&sct);CHKERRQ(ierr); 1335 ierr = VecDestroy(&cown);CHKERRQ(ierr); 1336 1337 /* compute edgeCut */ 1338 for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 1339 ierr = PetscMalloc1(cum,&work);CHKERRQ(ierr); 1340 ierr = ISLocalToGlobalMappingCreateIS(gid,&g2l);CHKERRQ(ierr); 1341 ierr = ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 1342 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1343 ierr = VecGetArray(acown,&array);CHKERRQ(ierr); 1344 for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 1345 PetscInt totl; 1346 1347 totl = start[c+1]-start[c]; 1348 ierr = ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work);CHKERRQ(ierr); 1349 for (i = 0; i < totl; i++) { 1350 if (work[i] < 0) { 1351 ect += 1; 1352 ectn += (array[i + start[c]] != nid) ? 0 : 1; 1353 } 1354 } 1355 } 1356 ierr = PetscFree(work);CHKERRQ(ierr); 1357 ierr = VecRestoreArray(acown,&array);CHKERRQ(ierr); 1358 lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 1359 lm[1] = -numVertices; 1360 ierr = MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm);CHKERRMPI(ierr); 1361 ierr = PetscViewerASCIIPrintf(viewer," Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]);CHKERRQ(ierr); 1362 lm[0] = ect; /* edgeCut */ 1363 lm[1] = ectn; /* node-aware edgeCut */ 1364 lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 1365 ierr = MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr); 1366 ierr = PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]);CHKERRQ(ierr); 1367 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1368 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); 1369 #else 1370 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0);CHKERRQ(ierr); 1371 #endif 1372 ierr = ISLocalToGlobalMappingDestroy(&g2l);CHKERRQ(ierr); 1373 ierr = PetscFree(start);CHKERRQ(ierr); 1374 ierr = PetscFree(adjacency);CHKERRQ(ierr); 1375 ierr = VecDestroy(&acown);CHKERRQ(ierr); 1376 } else { 1377 const char *name; 1378 PetscInt *sizes, *hybsizes, *ghostsizes; 1379 PetscInt locDepth, depth, cellHeight, dim, d; 1380 PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1381 PetscInt numLabels, l, maxSize = 17; 1382 DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1383 MPI_Comm comm; 1384 PetscMPIInt size, rank; 1385 1386 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1387 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1388 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1389 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1390 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 1391 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 1392 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1393 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1394 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 1395 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 1396 ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRMPI(ierr); 1397 ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr); 1398 gcNum = gcEnd - gcStart; 1399 if (size < maxSize) {ierr = PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes);CHKERRQ(ierr);} 1400 else {ierr = PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes);CHKERRQ(ierr);} 1401 for (d = 0; d <= depth; d++) { 1402 PetscInt Nc[2] = {0, 0}, ict; 1403 1404 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 1405 if (pStart < pEnd) {ierr = DMPlexGetCellType(dm, pStart, &ct0);CHKERRQ(ierr);} 1406 ict = ct0; 1407 ierr = MPI_Bcast(&ict, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1408 ct0 = (DMPolytopeType) ict; 1409 for (p = pStart; p < pEnd; ++p) { 1410 DMPolytopeType ct; 1411 1412 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 1413 if (ct == ct0) ++Nc[0]; 1414 else ++Nc[1]; 1415 } 1416 if (size < maxSize) { 1417 ierr = MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1418 ierr = MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1419 if (d == depth) {ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);} 1420 ierr = PetscViewerASCIIPrintf(viewer, " Number of %D-cells per rank:", (depth == 1) && d ? dim : d);CHKERRQ(ierr); 1421 for (p = 0; p < size; ++p) { 1422 if (rank == 0) { 1423 ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]);CHKERRQ(ierr); 1424 if (hybsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]);CHKERRQ(ierr);} 1425 if (ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);} 1426 } 1427 } 1428 } else { 1429 PetscInt locMinMax[2]; 1430 1431 locMinMax[0] = Nc[0]+Nc[1]; locMinMax[1] = Nc[0]+Nc[1]; 1432 ierr = PetscGlobalMinMaxInt(comm, locMinMax, sizes);CHKERRQ(ierr); 1433 locMinMax[0] = Nc[1]; locMinMax[1] = Nc[1]; 1434 ierr = PetscGlobalMinMaxInt(comm, locMinMax, hybsizes);CHKERRQ(ierr); 1435 if (d == depth) { 1436 locMinMax[0] = gcNum; locMinMax[1] = gcNum; 1437 ierr = PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes);CHKERRQ(ierr); 1438 } 1439 ierr = PetscViewerASCIIPrintf(viewer, " Min/Max of %D-cells per rank:", (depth == 1) && d ? dim : d);CHKERRQ(ierr); 1440 ierr = PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]);CHKERRQ(ierr); 1441 if (hybsizes[0] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]);CHKERRQ(ierr);} 1442 if (ghostsizes[0] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]);CHKERRQ(ierr);} 1443 } 1444 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 1445 } 1446 ierr = PetscFree3(sizes, hybsizes, ghostsizes);CHKERRQ(ierr); 1447 { 1448 const PetscReal *maxCell; 1449 const PetscReal *L; 1450 const DMBoundaryType *bd; 1451 PetscBool per, localized; 1452 1453 ierr = DMGetPeriodicity(dm, &per, &maxCell, &L, &bd);CHKERRQ(ierr); 1454 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 1455 if (per) { 1456 ierr = PetscViewerASCIIPrintf(viewer, "Periodic mesh (");CHKERRQ(ierr); 1457 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1458 for (d = 0; d < dim; ++d) { 1459 if (bd && d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1460 if (bd) {ierr = PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]]);CHKERRQ(ierr);} 1461 } 1462 ierr = PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized");CHKERRQ(ierr); 1463 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1464 } 1465 } 1466 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 1467 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 1468 for (l = 0; l < numLabels; ++l) { 1469 DMLabel label; 1470 const char *name; 1471 IS valueIS; 1472 const PetscInt *values; 1473 PetscInt numValues, v; 1474 1475 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 1476 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1477 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 1478 ierr = PetscViewerASCIIPrintf(viewer, " %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr); 1479 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 1480 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 1481 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1482 for (v = 0; v < numValues; ++v) { 1483 PetscInt size; 1484 1485 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 1486 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1487 ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr); 1488 } 1489 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 1490 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1491 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 1492 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 1493 } 1494 { 1495 char **labelNames; 1496 PetscInt Nl = numLabels; 1497 PetscBool flg; 1498 1499 ierr = PetscMalloc1(Nl, &labelNames);CHKERRQ(ierr); 1500 ierr = PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg);CHKERRQ(ierr); 1501 for (l = 0; l < Nl; ++l) { 1502 DMLabel label; 1503 1504 ierr = DMHasLabel(dm, labelNames[l], &flg);CHKERRQ(ierr); 1505 if (flg) { 1506 ierr = DMGetLabel(dm, labelNames[l], &label);CHKERRQ(ierr); 1507 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 1508 } 1509 ierr = PetscFree(labelNames[l]);CHKERRQ(ierr); 1510 } 1511 ierr = PetscFree(labelNames);CHKERRQ(ierr); 1512 } 1513 /* If no fields are specified, people do not want to see adjacency */ 1514 if (dm->Nf) { 1515 PetscInt f; 1516 1517 for (f = 0; f < dm->Nf; ++f) { 1518 const char *name; 1519 1520 ierr = PetscObjectGetName(dm->fields[f].disc, &name);CHKERRQ(ierr); 1521 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Field %s:\n", name);CHKERRQ(ierr);} 1522 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1523 if (dm->fields[f].label) {ierr = DMLabelView(dm->fields[f].label, viewer);CHKERRQ(ierr);} 1524 if (dm->fields[f].adjacency[0]) { 1525 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n");CHKERRQ(ierr);} 1526 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM\n");CHKERRQ(ierr);} 1527 } else { 1528 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FEM\n");CHKERRQ(ierr);} 1529 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n");CHKERRQ(ierr);} 1530 } 1531 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1532 } 1533 } 1534 ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr); 1535 if (cdm) { 1536 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1537 ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr); 1538 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1539 } 1540 } 1541 PetscFunctionReturn(0); 1542 } 1543 1544 static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1545 { 1546 DMPolytopeType ct; 1547 PetscMPIInt rank; 1548 PetscInt cdim; 1549 PetscErrorCode ierr; 1550 1551 PetscFunctionBegin; 1552 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1553 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1554 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 1555 switch (ct) { 1556 case DM_POLYTOPE_SEGMENT: 1557 case DM_POLYTOPE_POINT_PRISM_TENSOR: 1558 switch (cdim) { 1559 case 1: 1560 { 1561 const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1562 const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1563 1564 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK);CHKERRQ(ierr); 1565 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), y+dy, PetscRealPart(coords[0]), y-dy, PETSC_DRAW_BLACK);CHKERRQ(ierr); 1566 ierr = PetscDrawLine(draw, PetscRealPart(coords[1]), y+dy, PetscRealPart(coords[1]), y-dy, PETSC_DRAW_BLACK);CHKERRQ(ierr); 1567 } 1568 break; 1569 case 2: 1570 { 1571 const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1572 const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1573 const PetscReal l = 0.1/PetscSqrtReal(dx*dx + dy*dy); 1574 1575 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1576 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); 1577 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); 1578 } 1579 break; 1580 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %D", cdim); 1581 } 1582 break; 1583 case DM_POLYTOPE_TRIANGLE: 1584 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1585 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1586 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1587 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1588 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1589 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1590 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1591 break; 1592 case DM_POLYTOPE_QUADRILATERAL: 1593 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1594 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1595 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1596 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1597 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1598 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1599 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1600 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1601 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1602 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1603 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1604 ierr = PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1605 break; 1606 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1607 } 1608 PetscFunctionReturn(0); 1609 } 1610 1611 static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1612 { 1613 DMPolytopeType ct; 1614 PetscReal centroid[2] = {0., 0.}; 1615 PetscMPIInt rank; 1616 PetscInt fillColor, v, e, d; 1617 PetscErrorCode ierr; 1618 1619 PetscFunctionBegin; 1620 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1621 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1622 fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2; 1623 switch (ct) { 1624 case DM_POLYTOPE_TRIANGLE: 1625 { 1626 PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1627 1628 for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;} 1629 for (e = 0; e < 3; ++e) { 1630 refCoords[0] = refVertices[e*2+0]; 1631 refCoords[1] = refVertices[e*2+1]; 1632 for (d = 1; d <= edgeDiv; ++d) { 1633 refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv; 1634 refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv; 1635 } 1636 ierr = DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords);CHKERRQ(ierr); 1637 for (d = 0; d < edgeDiv; ++d) { 1638 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); 1639 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); 1640 } 1641 } 1642 } 1643 break; 1644 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1645 } 1646 PetscFunctionReturn(0); 1647 } 1648 1649 static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1650 { 1651 PetscDraw draw; 1652 DM cdm; 1653 PetscSection coordSection; 1654 Vec coordinates; 1655 const PetscScalar *coords; 1656 PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1657 PetscReal *refCoords, *edgeCoords; 1658 PetscBool isnull, drawAffine = PETSC_TRUE; 1659 PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1660 PetscErrorCode ierr; 1661 1662 PetscFunctionBegin; 1663 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 1664 PetscCheckFalse(dim > 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim); 1665 ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL);CHKERRQ(ierr); 1666 if (!drawAffine) {ierr = PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords);CHKERRQ(ierr);} 1667 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 1668 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1669 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 1670 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1671 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1672 1673 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 1674 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 1675 if (isnull) PetscFunctionReturn(0); 1676 ierr = PetscDrawSetTitle(draw, "Mesh");CHKERRQ(ierr); 1677 1678 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 1679 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 1680 for (c = 0; c < N; c += dim) { 1681 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 1682 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1683 } 1684 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 1685 ierr = MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1686 ierr = MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1687 ierr = PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]);CHKERRQ(ierr); 1688 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 1689 1690 for (c = cStart; c < cEnd; ++c) { 1691 PetscScalar *coords = NULL; 1692 PetscInt numCoords; 1693 1694 ierr = DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords);CHKERRQ(ierr); 1695 if (drawAffine) { 1696 ierr = DMPlexDrawCell(dm, draw, c, coords);CHKERRQ(ierr); 1697 } else { 1698 ierr = DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords);CHKERRQ(ierr); 1699 } 1700 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 1701 } 1702 if (!drawAffine) {ierr = PetscFree2(refCoords, edgeCoords);CHKERRQ(ierr);} 1703 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1704 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 1705 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 1706 PetscFunctionReturn(0); 1707 } 1708 1709 #if defined(PETSC_HAVE_EXODUSII) 1710 #include <exodusII.h> 1711 #include <petscviewerexodusii.h> 1712 #endif 1713 1714 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1715 { 1716 PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1717 char name[PETSC_MAX_PATH_LEN]; 1718 PetscErrorCode ierr; 1719 1720 PetscFunctionBegin; 1721 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1722 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1723 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1724 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1725 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1726 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 1727 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 1728 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus);CHKERRQ(ierr); 1729 if (iascii) { 1730 PetscViewerFormat format; 1731 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1732 if (format == PETSC_VIEWER_ASCII_GLVIS) { 1733 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1734 } else { 1735 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 1736 } 1737 } else if (ishdf5) { 1738 #if defined(PETSC_HAVE_HDF5) 1739 ierr = DMPlexView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1740 #else 1741 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1742 #endif 1743 } else if (isvtk) { 1744 ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr); 1745 } else if (isdraw) { 1746 ierr = DMPlexView_Draw(dm, viewer);CHKERRQ(ierr); 1747 } else if (isglvis) { 1748 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1749 #if defined(PETSC_HAVE_EXODUSII) 1750 } else if (isexodus) { 1751 /* 1752 exodusII requires that all sets be part of exactly one cell set. 1753 If the dm does not have a "Cell Sets" label defined, we create one 1754 with ID 1, containig all cells. 1755 Note that if the Cell Sets label is defined but does not cover all cells, 1756 we may still have a problem. This should probably be checked here or in the viewer; 1757 */ 1758 PetscInt numCS; 1759 ierr = DMGetLabelSize(dm,"Cell Sets",&numCS);CHKERRQ(ierr); 1760 if (!numCS) { 1761 PetscInt cStart, cEnd, c; 1762 ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr); 1763 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1764 for (c = cStart; c < cEnd; ++c) {ierr = DMSetLabelValue(dm, "Cell Sets", c, 1);CHKERRQ(ierr);} 1765 } 1766 ierr = DMView_PlexExodusII(dm, viewer);CHKERRQ(ierr); 1767 #endif 1768 } else { 1769 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1770 } 1771 /* Optionally view the partition */ 1772 ierr = PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg);CHKERRQ(ierr); 1773 if (flg) { 1774 Vec ranks; 1775 ierr = DMPlexCreateRankField(dm, &ranks);CHKERRQ(ierr); 1776 ierr = VecView(ranks, viewer);CHKERRQ(ierr); 1777 ierr = VecDestroy(&ranks);CHKERRQ(ierr); 1778 } 1779 /* Optionally view a label */ 1780 ierr = PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg);CHKERRQ(ierr); 1781 if (flg) { 1782 DMLabel label; 1783 Vec val; 1784 1785 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1786 PetscCheckFalse(!label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 1787 ierr = DMPlexCreateLabelField(dm, label, &val);CHKERRQ(ierr); 1788 ierr = VecView(val, viewer);CHKERRQ(ierr); 1789 ierr = VecDestroy(&val);CHKERRQ(ierr); 1790 } 1791 PetscFunctionReturn(0); 1792 } 1793 1794 /*@ 1795 DMPlexTopologyView - Saves a DMPlex topology into a file 1796 1797 Collective on DM 1798 1799 Input Parameters: 1800 + dm - The DM whose topology is to be saved 1801 - viewer - The PetscViewer for saving 1802 1803 Level: advanced 1804 1805 .seealso: DMView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexTopologyLoad() 1806 @*/ 1807 PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 1808 { 1809 PetscBool ishdf5; 1810 PetscErrorCode ierr; 1811 1812 PetscFunctionBegin; 1813 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1814 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1815 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1816 ierr = PetscLogEventBegin(DMPLEX_TopologyView,viewer,0,0,0);CHKERRQ(ierr); 1817 if (ishdf5) { 1818 #if defined(PETSC_HAVE_HDF5) 1819 PetscViewerFormat format; 1820 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1821 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1822 IS globalPointNumbering; 1823 1824 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1825 ierr = DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1826 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1827 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 1828 #else 1829 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1830 #endif 1831 } 1832 ierr = PetscLogEventEnd(DMPLEX_TopologyView,viewer,0,0,0);CHKERRQ(ierr); 1833 PetscFunctionReturn(0); 1834 } 1835 1836 /*@ 1837 DMPlexCoordinatesView - Saves DMPlex coordinates into a file 1838 1839 Collective on DM 1840 1841 Input Parameters: 1842 + dm - The DM whose coordinates are to be saved 1843 - viewer - The PetscViewer for saving 1844 1845 Level: advanced 1846 1847 .seealso: DMView(), DMPlexTopologyView(), DMPlexLabelsView(), DMPlexCoordinatesLoad() 1848 @*/ 1849 PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 1850 { 1851 PetscBool ishdf5; 1852 PetscErrorCode ierr; 1853 1854 PetscFunctionBegin; 1855 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1856 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1857 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1858 ierr = PetscLogEventBegin(DMPLEX_CoordinatesView,viewer,0,0,0);CHKERRQ(ierr); 1859 if (ishdf5) { 1860 #if defined(PETSC_HAVE_HDF5) 1861 PetscViewerFormat format; 1862 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1863 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1864 ierr = DMPlexCoordinatesView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1865 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1866 #else 1867 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1868 #endif 1869 } 1870 ierr = PetscLogEventEnd(DMPLEX_CoordinatesView,viewer,0,0,0);CHKERRQ(ierr); 1871 PetscFunctionReturn(0); 1872 } 1873 1874 /*@ 1875 DMPlexLabelsView - Saves DMPlex labels into a file 1876 1877 Collective on DM 1878 1879 Input Parameters: 1880 + dm - The DM whose labels are to be saved 1881 - viewer - The PetscViewer for saving 1882 1883 Level: advanced 1884 1885 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsLoad() 1886 @*/ 1887 PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1888 { 1889 PetscBool ishdf5; 1890 PetscErrorCode ierr; 1891 1892 PetscFunctionBegin; 1893 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1894 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1895 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1896 ierr = PetscLogEventBegin(DMPLEX_LabelsView,viewer,0,0,0);CHKERRQ(ierr); 1897 if (ishdf5) { 1898 #if defined(PETSC_HAVE_HDF5) 1899 IS globalPointNumbering; 1900 PetscViewerFormat format; 1901 1902 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1903 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1904 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1905 ierr = DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1906 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1907 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1908 #else 1909 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1910 #endif 1911 } 1912 ierr = PetscLogEventEnd(DMPLEX_LabelsView,viewer,0,0,0);CHKERRQ(ierr); 1913 PetscFunctionReturn(0); 1914 } 1915 1916 /*@ 1917 DMPlexSectionView - Saves a section associated with a DMPlex 1918 1919 Collective on DM 1920 1921 Input Parameters: 1922 + dm - The DM that contains the topology on which the section to be saved is defined 1923 . viewer - The PetscViewer for saving 1924 - sectiondm - The DM that contains the section to be saved 1925 1926 Level: advanced 1927 1928 Notes: 1929 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. 1930 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 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexGlobalVectorView(), DMPlexLocalVectorView(), PetscSectionView(), DMPlexSectionLoad() 1934 @*/ 1935 PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1936 { 1937 PetscBool ishdf5; 1938 PetscErrorCode ierr; 1939 1940 PetscFunctionBegin; 1941 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1942 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1943 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1944 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 1945 ierr = PetscLogEventBegin(DMPLEX_SectionView,viewer,0,0,0);CHKERRQ(ierr); 1946 if (ishdf5) { 1947 #if defined(PETSC_HAVE_HDF5) 1948 ierr = DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm);CHKERRQ(ierr); 1949 #else 1950 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1951 #endif 1952 } 1953 ierr = PetscLogEventEnd(DMPLEX_SectionView,viewer,0,0,0);CHKERRQ(ierr); 1954 PetscFunctionReturn(0); 1955 } 1956 1957 /*@ 1958 DMPlexGlobalVectorView - Saves a global vector 1959 1960 Collective on DM 1961 1962 Input Parameters: 1963 + dm - The DM that represents the topology 1964 . viewer - The PetscViewer to save data with 1965 . sectiondm - The DM that contains the global section on which vec is defined 1966 - vec - The global vector to be saved 1967 1968 Level: advanced 1969 1970 Notes: 1971 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. 1972 1973 Typical calling sequence 1974 $ DMCreate(PETSC_COMM_WORLD, &dm); 1975 $ DMSetType(dm, DMPLEX); 1976 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1977 $ DMClone(dm, §iondm); 1978 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1979 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1980 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1981 $ PetscSectionSetChart(section, pStart, pEnd); 1982 $ PetscSectionSetUp(section); 1983 $ DMSetLocalSection(sectiondm, section); 1984 $ PetscSectionDestroy(§ion); 1985 $ DMGetGlobalVector(sectiondm, &vec); 1986 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1987 $ DMPlexTopologyView(dm, viewer); 1988 $ DMPlexSectionView(dm, viewer, sectiondm); 1989 $ DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 1990 $ DMRestoreGlobalVector(sectiondm, &vec); 1991 $ DMDestroy(§iondm); 1992 $ DMDestroy(&dm); 1993 1994 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexLocalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1995 @*/ 1996 PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1997 { 1998 PetscBool ishdf5; 1999 PetscErrorCode ierr; 2000 2001 PetscFunctionBegin; 2002 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2003 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2004 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2005 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 2006 /* Check consistency */ 2007 { 2008 PetscSection section; 2009 PetscBool includesConstraints; 2010 PetscInt m, m1; 2011 2012 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2013 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 2014 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2015 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2016 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2017 PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 2018 } 2019 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2020 ierr = PetscLogEventBegin(DMPLEX_GlobalVectorView,viewer,0,0,0);CHKERRQ(ierr); 2021 if (ishdf5) { 2022 #if defined(PETSC_HAVE_HDF5) 2023 ierr = DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 2024 #else 2025 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2026 #endif 2027 } 2028 ierr = PetscLogEventEnd(DMPLEX_GlobalVectorView,viewer,0,0,0);CHKERRQ(ierr); 2029 PetscFunctionReturn(0); 2030 } 2031 2032 /*@ 2033 DMPlexLocalVectorView - Saves a local vector 2034 2035 Collective on DM 2036 2037 Input Parameters: 2038 + dm - The DM that represents the topology 2039 . viewer - The PetscViewer to save data with 2040 . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm 2041 - vec - The local vector to be saved 2042 2043 Level: advanced 2044 2045 Notes: 2046 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. 2047 2048 Typical calling sequence 2049 $ DMCreate(PETSC_COMM_WORLD, &dm); 2050 $ DMSetType(dm, DMPLEX); 2051 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2052 $ DMClone(dm, §iondm); 2053 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2054 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2055 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 2056 $ PetscSectionSetChart(section, pStart, pEnd); 2057 $ PetscSectionSetUp(section); 2058 $ DMSetLocalSection(sectiondm, section); 2059 $ DMGetLocalVector(sectiondm, &vec); 2060 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2061 $ DMPlexTopologyView(dm, viewer); 2062 $ DMPlexSectionView(dm, viewer, sectiondm); 2063 $ DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 2064 $ DMRestoreLocalVector(sectiondm, &vec); 2065 $ DMDestroy(§iondm); 2066 $ DMDestroy(&dm); 2067 2068 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexGlobalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 2069 @*/ 2070 PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2071 { 2072 PetscBool ishdf5; 2073 PetscErrorCode ierr; 2074 2075 PetscFunctionBegin; 2076 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2077 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2078 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2079 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 2080 /* Check consistency */ 2081 { 2082 PetscSection section; 2083 PetscBool includesConstraints; 2084 PetscInt m, m1; 2085 2086 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2087 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 2088 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2089 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2090 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2091 PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 2092 } 2093 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2094 ierr = PetscLogEventBegin(DMPLEX_LocalVectorView,viewer,0,0,0);CHKERRQ(ierr); 2095 if (ishdf5) { 2096 #if defined(PETSC_HAVE_HDF5) 2097 ierr = DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 2098 #else 2099 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2100 #endif 2101 } 2102 ierr = PetscLogEventEnd(DMPLEX_LocalVectorView,viewer,0,0,0);CHKERRQ(ierr); 2103 PetscFunctionReturn(0); 2104 } 2105 2106 PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 2107 { 2108 PetscBool ishdf5; 2109 PetscErrorCode ierr; 2110 2111 PetscFunctionBegin; 2112 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2113 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2114 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2115 if (ishdf5) { 2116 #if defined(PETSC_HAVE_HDF5) 2117 PetscViewerFormat format; 2118 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2119 if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 2120 ierr = DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer);CHKERRQ(ierr); 2121 } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2122 ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 2123 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2124 PetscFunctionReturn(0); 2125 #else 2126 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2127 #endif 2128 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2129 } 2130 2131 /*@ 2132 DMPlexTopologyLoad - Loads a topology into a DMPlex 2133 2134 Collective on DM 2135 2136 Input Parameters: 2137 + dm - The DM into which the topology is loaded 2138 - viewer - The PetscViewer for the saved topology 2139 2140 Output Parameters: 2141 . 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 2142 2143 Level: advanced 2144 2145 .seealso: DMLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2146 @*/ 2147 PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2148 { 2149 PetscBool ishdf5; 2150 PetscErrorCode ierr; 2151 2152 PetscFunctionBegin; 2153 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2154 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2155 if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 2156 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2157 ierr = PetscLogEventBegin(DMPLEX_TopologyLoad,viewer,0,0,0);CHKERRQ(ierr); 2158 if (ishdf5) { 2159 #if defined(PETSC_HAVE_HDF5) 2160 PetscViewerFormat format; 2161 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2162 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2163 ierr = DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 2164 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2165 #else 2166 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2167 #endif 2168 } 2169 ierr = PetscLogEventEnd(DMPLEX_TopologyLoad,viewer,0,0,0);CHKERRQ(ierr); 2170 PetscFunctionReturn(0); 2171 } 2172 2173 /*@ 2174 DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 2175 2176 Collective on DM 2177 2178 Input Parameters: 2179 + dm - The DM into which the coordinates are loaded 2180 . viewer - The PetscViewer for the saved coordinates 2181 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2182 2183 Level: advanced 2184 2185 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2186 @*/ 2187 PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2188 { 2189 PetscBool ishdf5; 2190 PetscErrorCode ierr; 2191 2192 PetscFunctionBegin; 2193 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2194 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2195 PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 2196 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2197 ierr = PetscLogEventBegin(DMPLEX_CoordinatesLoad,viewer,0,0,0);CHKERRQ(ierr); 2198 if (ishdf5) { 2199 #if defined(PETSC_HAVE_HDF5) 2200 PetscViewerFormat format; 2201 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2202 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2203 ierr = DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 2204 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2205 #else 2206 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2207 #endif 2208 } 2209 ierr = PetscLogEventEnd(DMPLEX_CoordinatesLoad,viewer,0,0,0);CHKERRQ(ierr); 2210 PetscFunctionReturn(0); 2211 } 2212 2213 /*@ 2214 DMPlexLabelsLoad - Loads labels into a DMPlex 2215 2216 Collective on DM 2217 2218 Input Parameters: 2219 + dm - The DM into which the labels are loaded 2220 . viewer - The PetscViewer for the saved labels 2221 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2222 2223 Level: advanced 2224 2225 Notes: 2226 The PetscSF argument must not be NULL if the DM is distributed, otherwise an error occurs. 2227 2228 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2229 @*/ 2230 PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2231 { 2232 PetscBool ishdf5; 2233 PetscErrorCode ierr; 2234 2235 PetscFunctionBegin; 2236 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2237 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2238 if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 2239 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2240 ierr = PetscLogEventBegin(DMPLEX_LabelsLoad,viewer,0,0,0);CHKERRQ(ierr); 2241 if (ishdf5) { 2242 #if defined(PETSC_HAVE_HDF5) 2243 PetscViewerFormat format; 2244 2245 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2246 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2247 ierr = DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 2248 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2249 #else 2250 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2251 #endif 2252 } 2253 ierr = PetscLogEventEnd(DMPLEX_LabelsLoad,viewer,0,0,0);CHKERRQ(ierr); 2254 PetscFunctionReturn(0); 2255 } 2256 2257 /*@ 2258 DMPlexSectionLoad - Loads section into a DMPlex 2259 2260 Collective on DM 2261 2262 Input Parameters: 2263 + dm - The DM that represents the topology 2264 . viewer - The PetscViewer that represents the on-disk section (sectionA) 2265 . sectiondm - The DM into which the on-disk section (sectionA) is migrated 2266 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2267 2268 Output Parameters 2269 + 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) 2270 - 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) 2271 2272 Level: advanced 2273 2274 Notes: 2275 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. 2276 2277 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. 2278 2279 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. 2280 2281 Example using 2 processes: 2282 $ NX (number of points on dm): 4 2283 $ sectionA : the on-disk section 2284 $ vecA : a vector associated with sectionA 2285 $ sectionB : sectiondm's local section constructed in this function 2286 $ vecB (local) : a vector associated with sectiondm's local section 2287 $ vecB (global) : a vector associated with sectiondm's global section 2288 $ 2289 $ rank 0 rank 1 2290 $ vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2291 $ sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2292 $ sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2293 $ sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2294 $ [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2295 $ sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2296 $ sectionB->atlasDof : 1 0 1 | 1 3 2297 $ sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2298 $ vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2299 $ vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2300 $ 2301 $ where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2302 2303 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad(), PetscSectionLoad(), DMPlexSectionView() 2304 @*/ 2305 PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2306 { 2307 PetscBool ishdf5; 2308 PetscErrorCode ierr; 2309 2310 PetscFunctionBegin; 2311 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2312 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2313 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2314 PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 2315 if (globalDofSF) PetscValidPointer(globalDofSF, 5); 2316 if (localDofSF) PetscValidPointer(localDofSF, 6); 2317 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2318 ierr = PetscLogEventBegin(DMPLEX_SectionLoad,viewer,0,0,0);CHKERRQ(ierr); 2319 if (ishdf5) { 2320 #if defined(PETSC_HAVE_HDF5) 2321 ierr = DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF);CHKERRQ(ierr); 2322 #else 2323 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2324 #endif 2325 } 2326 ierr = PetscLogEventEnd(DMPLEX_SectionLoad,viewer,0,0,0);CHKERRQ(ierr); 2327 PetscFunctionReturn(0); 2328 } 2329 2330 /*@ 2331 DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 2332 2333 Collective on DM 2334 2335 Input Parameters: 2336 + dm - The DM that represents the topology 2337 . viewer - The PetscViewer that represents the on-disk vector data 2338 . sectiondm - The DM that contains the global section on which vec is defined 2339 . sf - The SF that migrates the on-disk vector data into vec 2340 - vec - The global vector to set values of 2341 2342 Level: advanced 2343 2344 Notes: 2345 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. 2346 2347 Typical calling sequence 2348 $ DMCreate(PETSC_COMM_WORLD, &dm); 2349 $ DMSetType(dm, DMPLEX); 2350 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2351 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2352 $ DMClone(dm, §iondm); 2353 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2354 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2355 $ DMGetGlobalVector(sectiondm, &vec); 2356 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2357 $ DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2358 $ DMRestoreGlobalVector(sectiondm, &vec); 2359 $ PetscSFDestroy(&gsf); 2360 $ PetscSFDestroy(&sfX); 2361 $ DMDestroy(§iondm); 2362 $ DMDestroy(&dm); 2363 2364 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexLocalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2365 @*/ 2366 PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2367 { 2368 PetscBool ishdf5; 2369 PetscErrorCode ierr; 2370 2371 PetscFunctionBegin; 2372 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2373 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2374 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2375 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2376 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2377 /* Check consistency */ 2378 { 2379 PetscSection section; 2380 PetscBool includesConstraints; 2381 PetscInt m, m1; 2382 2383 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2384 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 2385 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2386 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2387 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2388 PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 2389 } 2390 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2391 ierr = PetscLogEventBegin(DMPLEX_GlobalVectorLoad,viewer,0,0,0);CHKERRQ(ierr); 2392 if (ishdf5) { 2393 #if defined(PETSC_HAVE_HDF5) 2394 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2395 #else 2396 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2397 #endif 2398 } 2399 ierr = PetscLogEventEnd(DMPLEX_GlobalVectorLoad,viewer,0,0,0);CHKERRQ(ierr); 2400 PetscFunctionReturn(0); 2401 } 2402 2403 /*@ 2404 DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 2405 2406 Collective on DM 2407 2408 Input Parameters: 2409 + dm - The DM that represents the topology 2410 . viewer - The PetscViewer that represents the on-disk vector data 2411 . sectiondm - The DM that contains the local section on which vec is defined 2412 . sf - The SF that migrates the on-disk vector data into vec 2413 - vec - The local vector to set values of 2414 2415 Level: advanced 2416 2417 Notes: 2418 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. 2419 2420 Typical calling sequence 2421 $ DMCreate(PETSC_COMM_WORLD, &dm); 2422 $ DMSetType(dm, DMPLEX); 2423 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2424 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2425 $ DMClone(dm, §iondm); 2426 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2427 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2428 $ DMGetLocalVector(sectiondm, &vec); 2429 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2430 $ DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2431 $ DMRestoreLocalVector(sectiondm, &vec); 2432 $ PetscSFDestroy(&lsf); 2433 $ PetscSFDestroy(&sfX); 2434 $ DMDestroy(§iondm); 2435 $ DMDestroy(&dm); 2436 2437 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexGlobalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2438 @*/ 2439 PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2440 { 2441 PetscBool ishdf5; 2442 PetscErrorCode ierr; 2443 2444 PetscFunctionBegin; 2445 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2446 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2447 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2448 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2449 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2450 /* Check consistency */ 2451 { 2452 PetscSection section; 2453 PetscBool includesConstraints; 2454 PetscInt m, m1; 2455 2456 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2457 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 2458 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2459 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2460 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2461 PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 2462 } 2463 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2464 ierr = PetscLogEventBegin(DMPLEX_LocalVectorLoad,viewer,0,0,0);CHKERRQ(ierr); 2465 if (ishdf5) { 2466 #if defined(PETSC_HAVE_HDF5) 2467 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2468 #else 2469 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2470 #endif 2471 } 2472 ierr = PetscLogEventEnd(DMPLEX_LocalVectorLoad,viewer,0,0,0);CHKERRQ(ierr); 2473 PetscFunctionReturn(0); 2474 } 2475 2476 PetscErrorCode DMDestroy_Plex(DM dm) 2477 { 2478 DM_Plex *mesh = (DM_Plex*) dm->data; 2479 PetscErrorCode ierr; 2480 2481 PetscFunctionBegin; 2482 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr); 2483 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr); 2484 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL);CHKERRQ(ierr); 2485 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL);CHKERRQ(ierr); 2486 if (--mesh->refct > 0) PetscFunctionReturn(0); 2487 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 2488 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 2489 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 2490 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 2491 ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr); 2492 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 2493 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 2494 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 2495 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 2496 ierr = PetscFree(mesh->transformType);CHKERRQ(ierr); 2497 ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 2498 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 2499 ierr = ISDestroy(&mesh->subpointIS);CHKERRQ(ierr); 2500 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 2501 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 2502 ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 2503 ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 2504 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 2505 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 2506 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 2507 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 2508 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 2509 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 2510 ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr); 2511 ierr = PetscFree(mesh->neighbors);CHKERRQ(ierr); 2512 if (mesh->metricCtx) { ierr = PetscFree(mesh->metricCtx);CHKERRQ(ierr); } 2513 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 2514 ierr = PetscFree(mesh);CHKERRQ(ierr); 2515 PetscFunctionReturn(0); 2516 } 2517 2518 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2519 { 2520 PetscSection sectionGlobal; 2521 PetscInt bs = -1, mbs; 2522 PetscInt localSize; 2523 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2524 PetscErrorCode ierr; 2525 MatType mtype; 2526 ISLocalToGlobalMapping ltog; 2527 2528 PetscFunctionBegin; 2529 ierr = MatInitializePackage();CHKERRQ(ierr); 2530 mtype = dm->mattype; 2531 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 2532 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 2533 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 2534 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 2535 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 2536 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 2537 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 2538 ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr); 2539 if (mbs > 1) bs = mbs; 2540 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 2541 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 2542 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 2543 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 2544 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 2545 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 2546 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 2547 ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr); 2548 if (!isShell) { 2549 PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 2550 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2]; 2551 PetscInt pStart, pEnd, p, dof, cdof; 2552 2553 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 2554 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 2555 for (p = pStart; p < pEnd; ++p) { 2556 PetscInt bdof; 2557 2558 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 2559 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 2560 dof = dof < 0 ? -(dof+1) : dof; 2561 bdof = cdof && (dof-cdof) ? 1 : dof; 2562 if (dof) { 2563 if (bs < 0) {bs = bdof;} 2564 else if (bs != bdof) {bs = 1; break;} 2565 } 2566 } 2567 /* Must have same blocksize on all procs (some might have no points) */ 2568 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2569 bsLocal[1] = bs; 2570 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 2571 if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2572 else bs = bsMinMax[0]; 2573 bs = PetscMax(1,bs); 2574 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 2575 if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 2576 ierr = MatSetBlockSize(*J, bs);CHKERRQ(ierr); 2577 ierr = MatSetUp(*J);CHKERRQ(ierr); 2578 } else { 2579 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 2580 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 2581 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 2582 } 2583 } 2584 ierr = MatSetDM(*J, dm);CHKERRQ(ierr); 2585 PetscFunctionReturn(0); 2586 } 2587 2588 /*@ 2589 DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2590 2591 Not collective 2592 2593 Input Parameter: 2594 . mesh - The DMPlex 2595 2596 Output Parameters: 2597 . subsection - The subdomain section 2598 2599 Level: developer 2600 2601 .seealso: 2602 @*/ 2603 PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2604 { 2605 DM_Plex *mesh = (DM_Plex*) dm->data; 2606 PetscErrorCode ierr; 2607 2608 PetscFunctionBegin; 2609 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2610 if (!mesh->subdomainSection) { 2611 PetscSection section; 2612 PetscSF sf; 2613 2614 ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr); 2615 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 2616 ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr); 2617 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 2618 } 2619 *subsection = mesh->subdomainSection; 2620 PetscFunctionReturn(0); 2621 } 2622 2623 /*@ 2624 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2625 2626 Not collective 2627 2628 Input Parameter: 2629 . mesh - The DMPlex 2630 2631 Output Parameters: 2632 + pStart - The first mesh point 2633 - pEnd - The upper bound for mesh points 2634 2635 Level: beginner 2636 2637 .seealso: DMPlexCreate(), DMPlexSetChart() 2638 @*/ 2639 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2640 { 2641 DM_Plex *mesh = (DM_Plex*) dm->data; 2642 PetscErrorCode ierr; 2643 2644 PetscFunctionBegin; 2645 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2646 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2647 PetscFunctionReturn(0); 2648 } 2649 2650 /*@ 2651 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2652 2653 Not collective 2654 2655 Input Parameters: 2656 + mesh - The DMPlex 2657 . pStart - The first mesh point 2658 - pEnd - The upper bound for mesh points 2659 2660 Output Parameters: 2661 2662 Level: beginner 2663 2664 .seealso: DMPlexCreate(), DMPlexGetChart() 2665 @*/ 2666 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2667 { 2668 DM_Plex *mesh = (DM_Plex*) dm->data; 2669 PetscErrorCode ierr; 2670 2671 PetscFunctionBegin; 2672 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2673 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2674 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 2675 PetscFunctionReturn(0); 2676 } 2677 2678 /*@ 2679 DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2680 2681 Not collective 2682 2683 Input Parameters: 2684 + mesh - The DMPlex 2685 - p - The point, which must lie in the chart set with DMPlexSetChart() 2686 2687 Output Parameter: 2688 . size - The cone size for point p 2689 2690 Level: beginner 2691 2692 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2693 @*/ 2694 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2695 { 2696 DM_Plex *mesh = (DM_Plex*) dm->data; 2697 PetscErrorCode ierr; 2698 2699 PetscFunctionBegin; 2700 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2701 PetscValidPointer(size, 3); 2702 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2703 PetscFunctionReturn(0); 2704 } 2705 2706 /*@ 2707 DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2708 2709 Not collective 2710 2711 Input Parameters: 2712 + mesh - The DMPlex 2713 . p - The point, which must lie in the chart set with DMPlexSetChart() 2714 - size - The cone size for point p 2715 2716 Output Parameter: 2717 2718 Note: 2719 This should be called after DMPlexSetChart(). 2720 2721 Level: beginner 2722 2723 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 2724 @*/ 2725 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2726 { 2727 DM_Plex *mesh = (DM_Plex*) dm->data; 2728 PetscErrorCode ierr; 2729 2730 PetscFunctionBegin; 2731 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2732 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2733 2734 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 2735 PetscFunctionReturn(0); 2736 } 2737 2738 /*@ 2739 DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2740 2741 Not collective 2742 2743 Input Parameters: 2744 + mesh - The DMPlex 2745 . p - The point, which must lie in the chart set with DMPlexSetChart() 2746 - size - The additional cone size for point p 2747 2748 Output Parameter: 2749 2750 Note: 2751 This should be called after DMPlexSetChart(). 2752 2753 Level: beginner 2754 2755 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 2756 @*/ 2757 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2758 { 2759 DM_Plex *mesh = (DM_Plex*) dm->data; 2760 PetscInt csize; 2761 PetscErrorCode ierr; 2762 2763 PetscFunctionBegin; 2764 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2765 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2766 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 2767 2768 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 2769 PetscFunctionReturn(0); 2770 } 2771 2772 /*@C 2773 DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2774 2775 Not collective 2776 2777 Input Parameters: 2778 + dm - The DMPlex 2779 - p - The point, which must lie in the chart set with DMPlexSetChart() 2780 2781 Output Parameter: 2782 . cone - An array of points which are on the in-edges for point p 2783 2784 Level: beginner 2785 2786 Fortran Notes: 2787 Since it returns an array, this routine is only available in Fortran 90, and you must 2788 include petsc.h90 in your code. 2789 You must also call DMPlexRestoreCone() after you finish using the returned array. 2790 DMPlexRestoreCone() is not needed/available in C. 2791 2792 .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart() 2793 @*/ 2794 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2795 { 2796 DM_Plex *mesh = (DM_Plex*) dm->data; 2797 PetscInt off; 2798 PetscErrorCode ierr; 2799 2800 PetscFunctionBegin; 2801 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2802 PetscValidPointer(cone, 3); 2803 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2804 *cone = &mesh->cones[off]; 2805 PetscFunctionReturn(0); 2806 } 2807 2808 /*@C 2809 DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 2810 2811 Not collective 2812 2813 Input Parameters: 2814 + dm - The DMPlex 2815 - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 2816 2817 Output Parameters: 2818 + pConesSection - PetscSection describing the layout of pCones 2819 - pCones - An array of points which are on the in-edges for the point set p 2820 2821 Level: intermediate 2822 2823 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart() 2824 @*/ 2825 PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 2826 { 2827 PetscSection cs, newcs; 2828 PetscInt *cones; 2829 PetscInt *newarr=NULL; 2830 PetscInt n; 2831 PetscErrorCode ierr; 2832 2833 PetscFunctionBegin; 2834 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 2835 ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr); 2836 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 2837 if (pConesSection) *pConesSection = newcs; 2838 if (pCones) { 2839 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 2840 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr); 2841 } 2842 PetscFunctionReturn(0); 2843 } 2844 2845 /*@ 2846 DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2847 2848 Not collective 2849 2850 Input Parameters: 2851 + dm - The DMPlex 2852 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2853 2854 Output Parameter: 2855 . expandedPoints - An array of vertices recursively expanded from input points 2856 2857 Level: advanced 2858 2859 Notes: 2860 Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2861 There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2862 2863 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth() 2864 @*/ 2865 PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2866 { 2867 IS *expandedPointsAll; 2868 PetscInt depth; 2869 PetscErrorCode ierr; 2870 2871 PetscFunctionBegin; 2872 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2873 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2874 PetscValidPointer(expandedPoints, 3); 2875 ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2876 *expandedPoints = expandedPointsAll[0]; 2877 ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]);CHKERRQ(ierr); 2878 ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2879 PetscFunctionReturn(0); 2880 } 2881 2882 /*@ 2883 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). 2884 2885 Not collective 2886 2887 Input Parameters: 2888 + dm - The DMPlex 2889 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2890 2891 Output Parameters: 2892 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2893 . expandedPoints - (optional) An array of index sets with recursively expanded cones 2894 - sections - (optional) An array of sections which describe mappings from points to their cone points 2895 2896 Level: advanced 2897 2898 Notes: 2899 Like DMPlexGetConeTuple() but recursive. 2900 2901 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. 2902 For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2903 2904 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: 2905 (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2906 (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2907 2908 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2909 @*/ 2910 PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2911 { 2912 const PetscInt *arr0=NULL, *cone=NULL; 2913 PetscInt *arr=NULL, *newarr=NULL; 2914 PetscInt d, depth_, i, n, newn, cn, co, start, end; 2915 IS *expandedPoints_; 2916 PetscSection *sections_; 2917 PetscErrorCode ierr; 2918 2919 PetscFunctionBegin; 2920 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2921 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2922 if (depth) PetscValidIntPointer(depth, 3); 2923 if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2924 if (sections) PetscValidPointer(sections, 5); 2925 ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr); 2926 ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr); 2927 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2928 ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr); 2929 ierr = PetscCalloc1(depth_, §ions_);CHKERRQ(ierr); 2930 arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2931 for (d=depth_-1; d>=0; d--) { 2932 ierr = PetscSectionCreate(PETSC_COMM_SELF, §ions_[d]);CHKERRQ(ierr); 2933 ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr); 2934 for (i=0; i<n; i++) { 2935 ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr); 2936 if (arr[i] >= start && arr[i] < end) { 2937 ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr); 2938 ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr); 2939 } else { 2940 ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr); 2941 } 2942 } 2943 ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr); 2944 ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr); 2945 ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr); 2946 for (i=0; i<n; i++) { 2947 ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr); 2948 ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr); 2949 if (cn > 1) { 2950 ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr); 2951 ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr); 2952 } else { 2953 newarr[co] = arr[i]; 2954 } 2955 } 2956 ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr); 2957 arr = newarr; 2958 n = newn; 2959 } 2960 ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr); 2961 *depth = depth_; 2962 if (expandedPoints) *expandedPoints = expandedPoints_; 2963 else { 2964 for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);} 2965 ierr = PetscFree(expandedPoints_);CHKERRQ(ierr); 2966 } 2967 if (sections) *sections = sections_; 2968 else { 2969 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(§ions_[d]);CHKERRQ(ierr);} 2970 ierr = PetscFree(sections_);CHKERRQ(ierr); 2971 } 2972 PetscFunctionReturn(0); 2973 } 2974 2975 /*@ 2976 DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2977 2978 Not collective 2979 2980 Input Parameters: 2981 + dm - The DMPlex 2982 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2983 2984 Output Parameters: 2985 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2986 . expandedPoints - (optional) An array of recursively expanded cones 2987 - sections - (optional) An array of sections which describe mappings from points to their cone points 2988 2989 Level: advanced 2990 2991 Notes: 2992 See DMPlexGetConeRecursive() for details. 2993 2994 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2995 @*/ 2996 PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2997 { 2998 PetscInt d, depth_; 2999 PetscErrorCode ierr; 3000 3001 PetscFunctionBegin; 3002 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 3003 PetscCheckFalse(depth && *depth != depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 3004 if (depth) *depth = 0; 3005 if (expandedPoints) { 3006 for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);} 3007 ierr = PetscFree(*expandedPoints);CHKERRQ(ierr); 3008 } 3009 if (sections) { 3010 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);} 3011 ierr = PetscFree(*sections);CHKERRQ(ierr); 3012 } 3013 PetscFunctionReturn(0); 3014 } 3015 3016 /*@ 3017 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 3018 3019 Not collective 3020 3021 Input Parameters: 3022 + mesh - The DMPlex 3023 . p - The point, which must lie in the chart set with DMPlexSetChart() 3024 - cone - An array of points which are on the in-edges for point p 3025 3026 Output Parameter: 3027 3028 Note: 3029 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 3030 3031 Level: beginner 3032 3033 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize() 3034 @*/ 3035 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3036 { 3037 DM_Plex *mesh = (DM_Plex*) dm->data; 3038 PetscInt pStart, pEnd; 3039 PetscInt dof, off, c; 3040 PetscErrorCode ierr; 3041 3042 PetscFunctionBegin; 3043 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3044 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3045 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3046 if (dof) PetscValidPointer(cone, 3); 3047 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3048 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); 3049 for (c = 0; c < dof; ++c) { 3050 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); 3051 mesh->cones[off+c] = cone[c]; 3052 } 3053 PetscFunctionReturn(0); 3054 } 3055 3056 /*@C 3057 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3058 3059 Not collective 3060 3061 Input Parameters: 3062 + mesh - The DMPlex 3063 - p - The point, which must lie in the chart set with DMPlexSetChart() 3064 3065 Output Parameter: 3066 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 3067 integer giving the prescription for cone traversal. 3068 3069 Level: beginner 3070 3071 Notes: 3072 The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3073 the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3074 of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 3075 with the identity. 3076 3077 Fortran Notes: 3078 Since it returns an array, this routine is only available in Fortran 90, and you must 3079 include petsc.h90 in your code. 3080 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 3081 DMPlexRestoreConeOrientation() is not needed/available in C. 3082 3083 .seealso: DMPolytopeTypeComposeOrientation(), DMPolytopeTypeComposeOrientationInv(), DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 3084 @*/ 3085 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3086 { 3087 DM_Plex *mesh = (DM_Plex*) dm->data; 3088 PetscInt off; 3089 PetscErrorCode ierr; 3090 3091 PetscFunctionBegin; 3092 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3093 if (PetscDefined(USE_DEBUG)) { 3094 PetscInt dof; 3095 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3096 if (dof) PetscValidPointer(coneOrientation, 3); 3097 } 3098 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3099 3100 *coneOrientation = &mesh->coneOrientations[off]; 3101 PetscFunctionReturn(0); 3102 } 3103 3104 /*@ 3105 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3106 3107 Not collective 3108 3109 Input Parameters: 3110 + mesh - The DMPlex 3111 . p - The point, which must lie in the chart set with DMPlexSetChart() 3112 - coneOrientation - An array of orientations 3113 Output Parameter: 3114 3115 Notes: 3116 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 3117 3118 The meaning of coneOrientation is detailed in DMPlexGetConeOrientation(). 3119 3120 Level: beginner 3121 3122 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3123 @*/ 3124 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3125 { 3126 DM_Plex *mesh = (DM_Plex*) dm->data; 3127 PetscInt pStart, pEnd; 3128 PetscInt dof, off, c; 3129 PetscErrorCode ierr; 3130 3131 PetscFunctionBegin; 3132 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3133 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3134 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3135 if (dof) PetscValidPointer(coneOrientation, 3); 3136 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3137 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); 3138 for (c = 0; c < dof; ++c) { 3139 PetscInt cdof, o = coneOrientation[c]; 3140 3141 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 3142 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); 3143 mesh->coneOrientations[off+c] = o; 3144 } 3145 PetscFunctionReturn(0); 3146 } 3147 3148 /*@ 3149 DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 3150 3151 Not collective 3152 3153 Input Parameters: 3154 + mesh - The DMPlex 3155 . p - The point, which must lie in the chart set with DMPlexSetChart() 3156 . conePos - The local index in the cone where the point should be put 3157 - conePoint - The mesh point to insert 3158 3159 Level: beginner 3160 3161 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3162 @*/ 3163 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3164 { 3165 DM_Plex *mesh = (DM_Plex*) dm->data; 3166 PetscInt pStart, pEnd; 3167 PetscInt dof, off; 3168 PetscErrorCode ierr; 3169 3170 PetscFunctionBegin; 3171 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3172 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3173 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); 3174 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); 3175 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3176 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3177 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); 3178 mesh->cones[off+conePos] = conePoint; 3179 PetscFunctionReturn(0); 3180 } 3181 3182 /*@ 3183 DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 3184 3185 Not collective 3186 3187 Input Parameters: 3188 + mesh - The DMPlex 3189 . p - The point, which must lie in the chart set with DMPlexSetChart() 3190 . conePos - The local index in the cone where the point should be put 3191 - coneOrientation - The point orientation to insert 3192 3193 Level: beginner 3194 3195 Notes: 3196 The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation(). 3197 3198 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3199 @*/ 3200 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3201 { 3202 DM_Plex *mesh = (DM_Plex*) dm->data; 3203 PetscInt pStart, pEnd; 3204 PetscInt dof, off; 3205 PetscErrorCode ierr; 3206 3207 PetscFunctionBegin; 3208 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3209 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3210 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); 3211 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3212 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3213 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); 3214 mesh->coneOrientations[off+conePos] = coneOrientation; 3215 PetscFunctionReturn(0); 3216 } 3217 3218 /*@ 3219 DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3220 3221 Not collective 3222 3223 Input Parameters: 3224 + mesh - The DMPlex 3225 - p - The point, which must lie in the chart set with DMPlexSetChart() 3226 3227 Output Parameter: 3228 . size - The support size for point p 3229 3230 Level: beginner 3231 3232 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 3233 @*/ 3234 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3235 { 3236 DM_Plex *mesh = (DM_Plex*) dm->data; 3237 PetscErrorCode ierr; 3238 3239 PetscFunctionBegin; 3240 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3241 PetscValidPointer(size, 3); 3242 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3243 PetscFunctionReturn(0); 3244 } 3245 3246 /*@ 3247 DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3248 3249 Not collective 3250 3251 Input Parameters: 3252 + mesh - The DMPlex 3253 . p - The point, which must lie in the chart set with DMPlexSetChart() 3254 - size - The support size for point p 3255 3256 Output Parameter: 3257 3258 Note: 3259 This should be called after DMPlexSetChart(). 3260 3261 Level: beginner 3262 3263 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 3264 @*/ 3265 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3266 { 3267 DM_Plex *mesh = (DM_Plex*) dm->data; 3268 PetscErrorCode ierr; 3269 3270 PetscFunctionBegin; 3271 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3272 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3273 3274 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 3275 PetscFunctionReturn(0); 3276 } 3277 3278 /*@C 3279 DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3280 3281 Not collective 3282 3283 Input Parameters: 3284 + mesh - The DMPlex 3285 - p - The point, which must lie in the chart set with DMPlexSetChart() 3286 3287 Output Parameter: 3288 . support - An array of points which are on the out-edges for point p 3289 3290 Level: beginner 3291 3292 Fortran Notes: 3293 Since it returns an array, this routine is only available in Fortran 90, and you must 3294 include petsc.h90 in your code. 3295 You must also call DMPlexRestoreSupport() after you finish using the returned array. 3296 DMPlexRestoreSupport() is not needed/available in C. 3297 3298 .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart() 3299 @*/ 3300 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3301 { 3302 DM_Plex *mesh = (DM_Plex*) dm->data; 3303 PetscInt off; 3304 PetscErrorCode ierr; 3305 3306 PetscFunctionBegin; 3307 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3308 PetscValidPointer(support, 3); 3309 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3310 *support = &mesh->supports[off]; 3311 PetscFunctionReturn(0); 3312 } 3313 3314 /*@ 3315 DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 3316 3317 Not collective 3318 3319 Input Parameters: 3320 + mesh - The DMPlex 3321 . p - The point, which must lie in the chart set with DMPlexSetChart() 3322 - support - An array of points which are on the out-edges for point p 3323 3324 Output Parameter: 3325 3326 Note: 3327 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 3328 3329 Level: beginner 3330 3331 .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 3332 @*/ 3333 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3334 { 3335 DM_Plex *mesh = (DM_Plex*) dm->data; 3336 PetscInt pStart, pEnd; 3337 PetscInt dof, off, c; 3338 PetscErrorCode ierr; 3339 3340 PetscFunctionBegin; 3341 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3342 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3343 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3344 if (dof) PetscValidPointer(support, 3); 3345 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3346 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); 3347 for (c = 0; c < dof; ++c) { 3348 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); 3349 mesh->supports[off+c] = support[c]; 3350 } 3351 PetscFunctionReturn(0); 3352 } 3353 3354 /*@ 3355 DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 3356 3357 Not collective 3358 3359 Input Parameters: 3360 + mesh - The DMPlex 3361 . p - The point, which must lie in the chart set with DMPlexSetChart() 3362 . supportPos - The local index in the cone where the point should be put 3363 - supportPoint - The mesh point to insert 3364 3365 Level: beginner 3366 3367 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3368 @*/ 3369 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3370 { 3371 DM_Plex *mesh = (DM_Plex*) dm->data; 3372 PetscInt pStart, pEnd; 3373 PetscInt dof, off; 3374 PetscErrorCode ierr; 3375 3376 PetscFunctionBegin; 3377 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3378 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3379 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3380 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3381 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); 3382 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); 3383 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); 3384 mesh->supports[off+supportPos] = supportPoint; 3385 PetscFunctionReturn(0); 3386 } 3387 3388 /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3389 PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3390 { 3391 switch (ct) { 3392 case DM_POLYTOPE_SEGMENT: 3393 if (o == -1) return -2; 3394 break; 3395 case DM_POLYTOPE_TRIANGLE: 3396 if (o == -3) return -1; 3397 if (o == -2) return -3; 3398 if (o == -1) return -2; 3399 break; 3400 case DM_POLYTOPE_QUADRILATERAL: 3401 if (o == -4) return -2; 3402 if (o == -3) return -1; 3403 if (o == -2) return -4; 3404 if (o == -1) return -3; 3405 break; 3406 default: return o; 3407 } 3408 return o; 3409 } 3410 3411 /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3412 PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3413 { 3414 switch (ct) { 3415 case DM_POLYTOPE_SEGMENT: 3416 if ((o == -2) || (o == 1)) return -1; 3417 if (o == -1) return 0; 3418 break; 3419 case DM_POLYTOPE_TRIANGLE: 3420 if (o == -3) return -2; 3421 if (o == -2) return -1; 3422 if (o == -1) return -3; 3423 break; 3424 case DM_POLYTOPE_QUADRILATERAL: 3425 if (o == -4) return -2; 3426 if (o == -3) return -1; 3427 if (o == -2) return -4; 3428 if (o == -1) return -3; 3429 break; 3430 default: return o; 3431 } 3432 return o; 3433 } 3434 3435 /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3436 PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3437 { 3438 PetscInt pStart, pEnd, p; 3439 PetscErrorCode ierr; 3440 3441 PetscFunctionBegin; 3442 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3443 for (p = pStart; p < pEnd; ++p) { 3444 const PetscInt *cone, *ornt; 3445 PetscInt coneSize, c; 3446 3447 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3448 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 3449 ierr = DMPlexGetConeOrientation(dm, p, &ornt);CHKERRQ(ierr); 3450 for (c = 0; c < coneSize; ++c) { 3451 DMPolytopeType ct; 3452 const PetscInt o = ornt[c]; 3453 3454 ierr = DMPlexGetCellType(dm, cone[c], &ct);CHKERRQ(ierr); 3455 switch (ct) { 3456 case DM_POLYTOPE_SEGMENT: 3457 if ((o == -2) || (o == 1)) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3458 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, 0);CHKERRQ(ierr);} 3459 break; 3460 case DM_POLYTOPE_TRIANGLE: 3461 if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);} 3462 if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3463 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);} 3464 break; 3465 case DM_POLYTOPE_QUADRILATERAL: 3466 if (o == -4) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);} 3467 if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3468 if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -4);CHKERRQ(ierr);} 3469 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);} 3470 break; 3471 default: break; 3472 } 3473 } 3474 } 3475 PetscFunctionReturn(0); 3476 } 3477 3478 static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3479 { 3480 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3481 PetscInt *closure; 3482 const PetscInt *tmp = NULL, *tmpO = NULL; 3483 PetscInt off = 0, tmpSize, t; 3484 PetscErrorCode ierr; 3485 3486 PetscFunctionBeginHot; 3487 if (ornt) { 3488 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3489 if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3490 } 3491 if (*points) { 3492 closure = *points; 3493 } else { 3494 PetscInt maxConeSize, maxSupportSize; 3495 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3496 ierr = DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure);CHKERRQ(ierr); 3497 } 3498 if (useCone) { 3499 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 3500 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 3501 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 3502 } else { 3503 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 3504 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 3505 } 3506 if (ct == DM_POLYTOPE_UNKNOWN) { 3507 closure[off++] = p; 3508 closure[off++] = 0; 3509 for (t = 0; t < tmpSize; ++t) { 3510 closure[off++] = tmp[t]; 3511 closure[off++] = tmpO ? tmpO[t] : 0; 3512 } 3513 } else { 3514 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);CHKERRQ(ierr); 3515 3516 /* We assume that cells with a valid type have faces with a valid type */ 3517 closure[off++] = p; 3518 closure[off++] = ornt; 3519 for (t = 0; t < tmpSize; ++t) { 3520 DMPolytopeType ft; 3521 3522 ierr = DMPlexGetCellType(dm, tmp[t], &ft);CHKERRQ(ierr); 3523 closure[off++] = tmp[arr[t]]; 3524 closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3525 } 3526 } 3527 if (numPoints) *numPoints = tmpSize+1; 3528 if (points) *points = closure; 3529 PetscFunctionReturn(0); 3530 } 3531 3532 /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */ 3533 static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3534 { 3535 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3536 const PetscInt *cone, *ornt; 3537 PetscInt *pts, *closure = NULL; 3538 DMPolytopeType ft; 3539 PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3540 PetscInt dim, coneSize, c, d, clSize, cl; 3541 PetscErrorCode ierr; 3542 3543 PetscFunctionBeginHot; 3544 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3545 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 3546 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3547 ierr = DMPlexGetConeOrientation(dm, point, &ornt);CHKERRQ(ierr); 3548 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3549 coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim+1)-1)/(maxConeSize-1)) : dim+1; 3550 supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1; 3551 maxSize = PetscMax(coneSeries, supportSeries); 3552 if (*points) {pts = *points;} 3553 else {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts);CHKERRQ(ierr);} 3554 c = 0; 3555 pts[c++] = point; 3556 pts[c++] = o; 3557 ierr = DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft);CHKERRQ(ierr); 3558 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure);CHKERRQ(ierr); 3559 for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 3560 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure);CHKERRQ(ierr); 3561 for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 3562 ierr = DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure);CHKERRQ(ierr); 3563 for (d = 2; d < coneSize; ++d) { 3564 ierr = DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft);CHKERRQ(ierr); 3565 pts[c++] = cone[arr[d*2+0]]; 3566 pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]); 3567 } 3568 if (dim >= 3) { 3569 for (d = 2; d < coneSize; ++d) { 3570 const PetscInt fpoint = cone[arr[d*2+0]]; 3571 const PetscInt *fcone, *fornt; 3572 PetscInt fconeSize, fc, i; 3573 3574 ierr = DMPlexGetCellType(dm, fpoint, &ft);CHKERRQ(ierr); 3575 const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d])); 3576 ierr = DMPlexGetConeSize(dm, fpoint, &fconeSize);CHKERRQ(ierr); 3577 ierr = DMPlexGetCone(dm, fpoint, &fcone);CHKERRQ(ierr); 3578 ierr = DMPlexGetConeOrientation(dm, fpoint, &fornt);CHKERRQ(ierr); 3579 for (fc = 0; fc < fconeSize; ++fc) { 3580 const PetscInt cp = fcone[farr[fc*2+0]]; 3581 const PetscInt co = farr[fc*2+1]; 3582 3583 for (i = 0; i < c; i += 2) if (pts[i] == cp) break; 3584 if (i == c) { 3585 ierr = DMPlexGetCellType(dm, cp, &ft);CHKERRQ(ierr); 3586 pts[c++] = cp; 3587 pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]); 3588 } 3589 } 3590 } 3591 } 3592 *numPoints = c/2; 3593 *points = pts; 3594 PetscFunctionReturn(0); 3595 } 3596 3597 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3598 { 3599 DMPolytopeType ct; 3600 PetscInt *closure, *fifo; 3601 PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3602 PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3603 PetscInt depth, maxSize; 3604 PetscErrorCode ierr; 3605 3606 PetscFunctionBeginHot; 3607 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3608 if (depth == 1) { 3609 ierr = DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points);CHKERRQ(ierr); 3610 PetscFunctionReturn(0); 3611 } 3612 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3613 if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3614 if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 3615 ierr = DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points);CHKERRQ(ierr); 3616 PetscFunctionReturn(0); 3617 } 3618 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3619 coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth+1)-1)/(maxConeSize-1)) : depth+1; 3620 supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1; 3621 maxSize = PetscMax(coneSeries, supportSeries); 3622 ierr = DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3623 if (*points) {closure = *points;} 3624 else {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure);CHKERRQ(ierr);} 3625 closure[closureSize++] = p; 3626 closure[closureSize++] = ornt; 3627 fifo[fifoSize++] = p; 3628 fifo[fifoSize++] = ornt; 3629 fifo[fifoSize++] = ct; 3630 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3631 while (fifoSize - fifoStart) { 3632 const PetscInt q = fifo[fifoStart++]; 3633 const PetscInt o = fifo[fifoStart++]; 3634 const DMPolytopeType qt = (DMPolytopeType) fifo[fifoStart++]; 3635 const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 3636 const PetscInt *tmp, *tmpO; 3637 PetscInt tmpSize, t; 3638 3639 if (PetscDefined(USE_DEBUG)) { 3640 PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2; 3641 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); 3642 } 3643 if (useCone) { 3644 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 3645 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 3646 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 3647 } else { 3648 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 3649 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 3650 tmpO = NULL; 3651 } 3652 for (t = 0; t < tmpSize; ++t) { 3653 const PetscInt ip = useCone && qarr ? qarr[t*2] : t; 3654 const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0; 3655 const PetscInt cp = tmp[ip]; 3656 ierr = DMPlexGetCellType(dm, cp, &ct);CHKERRQ(ierr); 3657 const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3658 PetscInt c; 3659 3660 /* Check for duplicate */ 3661 for (c = 0; c < closureSize; c += 2) { 3662 if (closure[c] == cp) break; 3663 } 3664 if (c == closureSize) { 3665 closure[closureSize++] = cp; 3666 closure[closureSize++] = co; 3667 fifo[fifoSize++] = cp; 3668 fifo[fifoSize++] = co; 3669 fifo[fifoSize++] = ct; 3670 } 3671 } 3672 } 3673 ierr = DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3674 if (numPoints) *numPoints = closureSize/2; 3675 if (points) *points = closure; 3676 PetscFunctionReturn(0); 3677 } 3678 3679 /*@C 3680 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3681 3682 Not collective 3683 3684 Input Parameters: 3685 + dm - The DMPlex 3686 . p - The mesh point 3687 - useCone - PETSC_TRUE for the closure, otherwise return the star 3688 3689 Input/Output Parameter: 3690 . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 3691 if NULL on input, internal storage will be returned, otherwise the provided array is used 3692 3693 Output Parameter: 3694 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3695 3696 Note: 3697 If using internal storage (points is NULL on input), each call overwrites the last output. 3698 3699 Fortran Notes: 3700 Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3701 3702 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3703 3704 Level: beginner 3705 3706 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3707 @*/ 3708 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3709 { 3710 PetscErrorCode ierr; 3711 3712 PetscFunctionBeginHot; 3713 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3714 if (numPoints) PetscValidIntPointer(numPoints, 4); 3715 if (points) PetscValidPointer(points, 5); 3716 ierr = DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points);CHKERRQ(ierr); 3717 PetscFunctionReturn(0); 3718 } 3719 3720 /*@C 3721 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3722 3723 Not collective 3724 3725 Input Parameters: 3726 + dm - The DMPlex 3727 . p - The mesh point 3728 . useCone - PETSC_TRUE for the closure, otherwise return the star 3729 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3730 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3731 3732 Note: 3733 If not using internal storage (points is not NULL on input), this call is unnecessary 3734 3735 Fortran Notes: 3736 Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3737 3738 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3739 3740 Level: beginner 3741 3742 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3743 @*/ 3744 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3745 { 3746 PetscErrorCode ierr; 3747 3748 PetscFunctionBeginHot; 3749 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3750 if (numPoints) *numPoints = 0; 3751 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr); 3752 PetscFunctionReturn(0); 3753 } 3754 3755 /*@ 3756 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3757 3758 Not collective 3759 3760 Input Parameter: 3761 . mesh - The DMPlex 3762 3763 Output Parameters: 3764 + maxConeSize - The maximum number of in-edges 3765 - maxSupportSize - The maximum number of out-edges 3766 3767 Level: beginner 3768 3769 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 3770 @*/ 3771 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3772 { 3773 DM_Plex *mesh = (DM_Plex*) dm->data; 3774 3775 PetscFunctionBegin; 3776 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3777 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 3778 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 3779 PetscFunctionReturn(0); 3780 } 3781 3782 PetscErrorCode DMSetUp_Plex(DM dm) 3783 { 3784 DM_Plex *mesh = (DM_Plex*) dm->data; 3785 PetscInt size; 3786 PetscErrorCode ierr; 3787 3788 PetscFunctionBegin; 3789 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3790 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 3791 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 3792 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 3793 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 3794 ierr = PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt));CHKERRQ(ierr); 3795 if (mesh->maxSupportSize) { 3796 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3797 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 3798 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 3799 ierr = PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt));CHKERRQ(ierr); 3800 } 3801 PetscFunctionReturn(0); 3802 } 3803 3804 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3805 { 3806 PetscErrorCode ierr; 3807 3808 PetscFunctionBegin; 3809 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 3810 ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 3811 if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3812 if (dm->useNatural && dm->sfMigration) { 3813 PetscSF sfMigrationInv,sfNatural; 3814 PetscSection section, sectionSeq; 3815 3816 (*subdm)->sfMigration = dm->sfMigration; 3817 ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr); 3818 ierr = DMGetLocalSection((*subdm), §ion);CHKERRQ(ierr); 3819 ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3820 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq);CHKERRQ(ierr); 3821 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3822 3823 ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3824 (*subdm)->sfNatural = sfNatural; 3825 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3826 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3827 } 3828 PetscFunctionReturn(0); 3829 } 3830 3831 PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 3832 { 3833 PetscErrorCode ierr; 3834 PetscInt i = 0; 3835 3836 PetscFunctionBegin; 3837 ierr = DMClone(dms[0], superdm);CHKERRQ(ierr); 3838 ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr); 3839 (*superdm)->useNatural = PETSC_FALSE; 3840 for (i = 0; i < len; i++) { 3841 if (dms[i]->useNatural && dms[i]->sfMigration) { 3842 PetscSF sfMigrationInv,sfNatural; 3843 PetscSection section, sectionSeq; 3844 3845 (*superdm)->sfMigration = dms[i]->sfMigration; 3846 ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr); 3847 (*superdm)->useNatural = PETSC_TRUE; 3848 ierr = DMGetLocalSection((*superdm), §ion);CHKERRQ(ierr); 3849 ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3850 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq);CHKERRQ(ierr); 3851 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3852 3853 ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3854 (*superdm)->sfNatural = sfNatural; 3855 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3856 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3857 break; 3858 } 3859 } 3860 PetscFunctionReturn(0); 3861 } 3862 3863 /*@ 3864 DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3865 3866 Not collective 3867 3868 Input Parameter: 3869 . mesh - The DMPlex 3870 3871 Output Parameter: 3872 3873 Note: 3874 This should be called after all calls to DMPlexSetCone() 3875 3876 Level: beginner 3877 3878 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 3879 @*/ 3880 PetscErrorCode DMPlexSymmetrize(DM dm) 3881 { 3882 DM_Plex *mesh = (DM_Plex*) dm->data; 3883 PetscInt *offsets; 3884 PetscInt supportSize; 3885 PetscInt pStart, pEnd, p; 3886 PetscErrorCode ierr; 3887 3888 PetscFunctionBegin; 3889 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3890 PetscCheckFalse(mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 3891 ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3892 /* Calculate support sizes */ 3893 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3894 for (p = pStart; p < pEnd; ++p) { 3895 PetscInt dof, off, c; 3896 3897 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3898 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3899 for (c = off; c < off+dof; ++c) { 3900 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 3901 } 3902 } 3903 for (p = pStart; p < pEnd; ++p) { 3904 PetscInt dof; 3905 3906 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3907 3908 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 3909 } 3910 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3911 /* Calculate supports */ 3912 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 3913 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 3914 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 3915 for (p = pStart; p < pEnd; ++p) { 3916 PetscInt dof, off, c; 3917 3918 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3919 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3920 for (c = off; c < off+dof; ++c) { 3921 const PetscInt q = mesh->cones[c]; 3922 PetscInt offS; 3923 3924 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 3925 3926 mesh->supports[offS+offsets[q]] = p; 3927 ++offsets[q]; 3928 } 3929 } 3930 ierr = PetscFree(offsets);CHKERRQ(ierr); 3931 ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3932 PetscFunctionReturn(0); 3933 } 3934 3935 static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3936 { 3937 IS stratumIS; 3938 PetscErrorCode ierr; 3939 3940 PetscFunctionBegin; 3941 if (pStart >= pEnd) PetscFunctionReturn(0); 3942 if (PetscDefined(USE_DEBUG)) { 3943 PetscInt qStart, qEnd, numLevels, level; 3944 PetscBool overlap = PETSC_FALSE; 3945 ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr); 3946 for (level = 0; level < numLevels; level++) { 3947 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3948 if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3949 } 3950 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); 3951 } 3952 ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr); 3953 ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr); 3954 ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 3955 PetscFunctionReturn(0); 3956 } 3957 3958 /*@ 3959 DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 3960 can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3961 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3962 the DAG. 3963 3964 Collective on dm 3965 3966 Input Parameter: 3967 . mesh - The DMPlex 3968 3969 Output Parameter: 3970 3971 Notes: 3972 Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3973 meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 3974 until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3975 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3976 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3977 3978 The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3979 if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3980 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 3981 to interpolate only that one (e0), so that 3982 $ cone(c0) = {e0, v2} 3983 $ cone(e0) = {v0, v1} 3984 If DMPlexStratify() is run on this mesh, it will give depths 3985 $ depth 0 = {v0, v1, v2} 3986 $ depth 1 = {e0, c0} 3987 where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3988 3989 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3990 3991 Level: beginner 3992 3993 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes() 3994 @*/ 3995 PetscErrorCode DMPlexStratify(DM dm) 3996 { 3997 DM_Plex *mesh = (DM_Plex*) dm->data; 3998 DMLabel label; 3999 PetscInt pStart, pEnd, p; 4000 PetscInt numRoots = 0, numLeaves = 0; 4001 PetscErrorCode ierr; 4002 4003 PetscFunctionBegin; 4004 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4005 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 4006 4007 /* Create depth label */ 4008 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4009 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 4010 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4011 4012 { 4013 /* Initialize roots and count leaves */ 4014 PetscInt sMin = PETSC_MAX_INT; 4015 PetscInt sMax = PETSC_MIN_INT; 4016 PetscInt coneSize, supportSize; 4017 4018 for (p = pStart; p < pEnd; ++p) { 4019 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 4020 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 4021 if (!coneSize && supportSize) { 4022 sMin = PetscMin(p, sMin); 4023 sMax = PetscMax(p, sMax); 4024 ++numRoots; 4025 } else if (!supportSize && coneSize) { 4026 ++numLeaves; 4027 } else if (!supportSize && !coneSize) { 4028 /* Isolated points */ 4029 sMin = PetscMin(p, sMin); 4030 sMax = PetscMax(p, sMax); 4031 } 4032 } 4033 ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr); 4034 } 4035 4036 if (numRoots + numLeaves == (pEnd - pStart)) { 4037 PetscInt sMin = PETSC_MAX_INT; 4038 PetscInt sMax = PETSC_MIN_INT; 4039 PetscInt coneSize, supportSize; 4040 4041 for (p = pStart; p < pEnd; ++p) { 4042 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 4043 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 4044 if (!supportSize && coneSize) { 4045 sMin = PetscMin(p, sMin); 4046 sMax = PetscMax(p, sMax); 4047 } 4048 } 4049 ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr); 4050 } else { 4051 PetscInt level = 0; 4052 PetscInt qStart, qEnd, q; 4053 4054 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 4055 while (qEnd > qStart) { 4056 PetscInt sMin = PETSC_MAX_INT; 4057 PetscInt sMax = PETSC_MIN_INT; 4058 4059 for (q = qStart; q < qEnd; ++q) { 4060 const PetscInt *support; 4061 PetscInt supportSize, s; 4062 4063 ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr); 4064 ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr); 4065 for (s = 0; s < supportSize; ++s) { 4066 sMin = PetscMin(support[s], sMin); 4067 sMax = PetscMax(support[s], sMax); 4068 } 4069 } 4070 ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr); 4071 ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr); 4072 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 4073 } 4074 } 4075 { /* just in case there is an empty process */ 4076 PetscInt numValues, maxValues = 0, v; 4077 4078 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 4079 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 4080 for (v = numValues; v < maxValues; v++) { 4081 ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr); 4082 } 4083 } 4084 ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr); 4085 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 4086 PetscFunctionReturn(0); 4087 } 4088 4089 PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4090 { 4091 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4092 PetscInt dim, depth, pheight, coneSize; 4093 PetscErrorCode ierr; 4094 4095 PetscFunctionBeginHot; 4096 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4097 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4098 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 4099 pheight = depth - pdepth; 4100 if (depth <= 1) { 4101 switch (pdepth) { 4102 case 0: ct = DM_POLYTOPE_POINT;break; 4103 case 1: 4104 switch (coneSize) { 4105 case 2: ct = DM_POLYTOPE_SEGMENT;break; 4106 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4107 case 4: 4108 switch (dim) { 4109 case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 4110 case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 4111 default: break; 4112 } 4113 break; 4114 case 5: ct = DM_POLYTOPE_PYRAMID;break; 4115 case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4116 case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 4117 default: break; 4118 } 4119 } 4120 } else { 4121 if (pdepth == 0) { 4122 ct = DM_POLYTOPE_POINT; 4123 } else if (pheight == 0) { 4124 switch (dim) { 4125 case 1: 4126 switch (coneSize) { 4127 case 2: ct = DM_POLYTOPE_SEGMENT;break; 4128 default: break; 4129 } 4130 break; 4131 case 2: 4132 switch (coneSize) { 4133 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4134 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4135 default: break; 4136 } 4137 break; 4138 case 3: 4139 switch (coneSize) { 4140 case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 4141 case 5: 4142 { 4143 const PetscInt *cone; 4144 PetscInt faceConeSize; 4145 4146 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 4147 ierr = DMPlexGetConeSize(dm, cone[0], &faceConeSize);CHKERRQ(ierr); 4148 switch (faceConeSize) { 4149 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4150 case 4: ct = DM_POLYTOPE_PYRAMID;break; 4151 } 4152 } 4153 break; 4154 case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 4155 default: break; 4156 } 4157 break; 4158 default: break; 4159 } 4160 } else if (pheight > 0) { 4161 switch (coneSize) { 4162 case 2: ct = DM_POLYTOPE_SEGMENT;break; 4163 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4164 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4165 default: break; 4166 } 4167 } 4168 } 4169 *pt = ct; 4170 PetscFunctionReturn(0); 4171 } 4172 4173 /*@ 4174 DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4175 4176 Collective on dm 4177 4178 Input Parameter: 4179 . mesh - The DMPlex 4180 4181 DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 4182 4183 Level: developer 4184 4185 Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 4186 internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 4187 automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 4188 4189 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel() 4190 @*/ 4191 PetscErrorCode DMPlexComputeCellTypes(DM dm) 4192 { 4193 DM_Plex *mesh; 4194 DMLabel ctLabel; 4195 PetscInt pStart, pEnd, p; 4196 PetscErrorCode ierr; 4197 4198 PetscFunctionBegin; 4199 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4200 mesh = (DM_Plex *) dm->data; 4201 ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr); 4202 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 4203 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4204 for (p = pStart; p < pEnd; ++p) { 4205 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4206 PetscInt pdepth; 4207 4208 ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr); 4209 ierr = DMPlexComputeCellType_Internal(dm, p, pdepth, &ct);CHKERRQ(ierr); 4210 PetscCheckFalse(ct == DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p); 4211 ierr = DMLabelSetValue(ctLabel, p, ct);CHKERRQ(ierr); 4212 } 4213 ierr = PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState);CHKERRQ(ierr); 4214 ierr = PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr); 4215 PetscFunctionReturn(0); 4216 } 4217 4218 /*@C 4219 DMPlexGetJoin - Get an array for the join of the set of points 4220 4221 Not Collective 4222 4223 Input Parameters: 4224 + dm - The DMPlex object 4225 . numPoints - The number of input points for the join 4226 - points - The input points 4227 4228 Output Parameters: 4229 + numCoveredPoints - The number of points in the join 4230 - coveredPoints - The points in the join 4231 4232 Level: intermediate 4233 4234 Note: Currently, this is restricted to a single level join 4235 4236 Fortran Notes: 4237 Since it returns an array, this routine is only available in Fortran 90, and you must 4238 include petsc.h90 in your code. 4239 4240 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4241 4242 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 4243 @*/ 4244 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4245 { 4246 DM_Plex *mesh = (DM_Plex*) dm->data; 4247 PetscInt *join[2]; 4248 PetscInt joinSize, i = 0; 4249 PetscInt dof, off, p, c, m; 4250 PetscErrorCode ierr; 4251 4252 PetscFunctionBegin; 4253 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4254 PetscValidIntPointer(points, 3); 4255 PetscValidIntPointer(numCoveredPoints, 4); 4256 PetscValidPointer(coveredPoints, 5); 4257 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4258 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4259 /* Copy in support of first point */ 4260 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 4261 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 4262 for (joinSize = 0; joinSize < dof; ++joinSize) { 4263 join[i][joinSize] = mesh->supports[off+joinSize]; 4264 } 4265 /* Check each successive support */ 4266 for (p = 1; p < numPoints; ++p) { 4267 PetscInt newJoinSize = 0; 4268 4269 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 4270 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 4271 for (c = 0; c < dof; ++c) { 4272 const PetscInt point = mesh->supports[off+c]; 4273 4274 for (m = 0; m < joinSize; ++m) { 4275 if (point == join[i][m]) { 4276 join[1-i][newJoinSize++] = point; 4277 break; 4278 } 4279 } 4280 } 4281 joinSize = newJoinSize; 4282 i = 1-i; 4283 } 4284 *numCoveredPoints = joinSize; 4285 *coveredPoints = join[i]; 4286 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4287 PetscFunctionReturn(0); 4288 } 4289 4290 /*@C 4291 DMPlexRestoreJoin - Restore an array for the join of the set of points 4292 4293 Not Collective 4294 4295 Input Parameters: 4296 + dm - The DMPlex object 4297 . numPoints - The number of input points for the join 4298 - points - The input points 4299 4300 Output Parameters: 4301 + numCoveredPoints - The number of points in the join 4302 - coveredPoints - The points in the join 4303 4304 Fortran Notes: 4305 Since it returns an array, this routine is only available in Fortran 90, and you must 4306 include petsc.h90 in your code. 4307 4308 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4309 4310 Level: intermediate 4311 4312 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 4313 @*/ 4314 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4315 { 4316 PetscErrorCode ierr; 4317 4318 PetscFunctionBegin; 4319 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4320 if (points) PetscValidIntPointer(points,3); 4321 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4322 PetscValidPointer(coveredPoints, 5); 4323 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4324 if (numCoveredPoints) *numCoveredPoints = 0; 4325 PetscFunctionReturn(0); 4326 } 4327 4328 /*@C 4329 DMPlexGetFullJoin - Get an array for the join of the set of points 4330 4331 Not Collective 4332 4333 Input Parameters: 4334 + dm - The DMPlex object 4335 . numPoints - The number of input points for the join 4336 - points - The input points 4337 4338 Output Parameters: 4339 + numCoveredPoints - The number of points in the join 4340 - coveredPoints - The points in the join 4341 4342 Fortran Notes: 4343 Since it returns an array, this routine is only available in Fortran 90, and you must 4344 include petsc.h90 in your code. 4345 4346 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4347 4348 Level: intermediate 4349 4350 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 4351 @*/ 4352 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4353 { 4354 DM_Plex *mesh = (DM_Plex*) dm->data; 4355 PetscInt *offsets, **closures; 4356 PetscInt *join[2]; 4357 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 4358 PetscInt p, d, c, m, ms; 4359 PetscErrorCode ierr; 4360 4361 PetscFunctionBegin; 4362 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4363 PetscValidIntPointer(points, 3); 4364 PetscValidIntPointer(numCoveredPoints, 4); 4365 PetscValidPointer(coveredPoints, 5); 4366 4367 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4368 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 4369 ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4370 ms = mesh->maxSupportSize; 4371 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 4372 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4373 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4374 4375 for (p = 0; p < numPoints; ++p) { 4376 PetscInt closureSize; 4377 4378 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 4379 4380 offsets[p*(depth+2)+0] = 0; 4381 for (d = 0; d < depth+1; ++d) { 4382 PetscInt pStart, pEnd, i; 4383 4384 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 4385 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4386 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4387 offsets[p*(depth+2)+d+1] = i; 4388 break; 4389 } 4390 } 4391 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4392 } 4393 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); 4394 } 4395 for (d = 0; d < depth+1; ++d) { 4396 PetscInt dof; 4397 4398 /* Copy in support of first point */ 4399 dof = offsets[d+1] - offsets[d]; 4400 for (joinSize = 0; joinSize < dof; ++joinSize) { 4401 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4402 } 4403 /* Check each successive cone */ 4404 for (p = 1; p < numPoints && joinSize; ++p) { 4405 PetscInt newJoinSize = 0; 4406 4407 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4408 for (c = 0; c < dof; ++c) { 4409 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4410 4411 for (m = 0; m < joinSize; ++m) { 4412 if (point == join[i][m]) { 4413 join[1-i][newJoinSize++] = point; 4414 break; 4415 } 4416 } 4417 } 4418 joinSize = newJoinSize; 4419 i = 1-i; 4420 } 4421 if (joinSize) break; 4422 } 4423 *numCoveredPoints = joinSize; 4424 *coveredPoints = join[i]; 4425 for (p = 0; p < numPoints; ++p) { 4426 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 4427 } 4428 ierr = PetscFree(closures);CHKERRQ(ierr); 4429 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4430 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4431 PetscFunctionReturn(0); 4432 } 4433 4434 /*@C 4435 DMPlexGetMeet - Get an array for the meet of the set of points 4436 4437 Not Collective 4438 4439 Input Parameters: 4440 + dm - The DMPlex object 4441 . numPoints - The number of input points for the meet 4442 - points - The input points 4443 4444 Output Parameters: 4445 + numCoveredPoints - The number of points in the meet 4446 - coveredPoints - The points in the meet 4447 4448 Level: intermediate 4449 4450 Note: Currently, this is restricted to a single level meet 4451 4452 Fortran Notes: 4453 Since it returns an array, this routine is only available in Fortran 90, and you must 4454 include petsc.h90 in your code. 4455 4456 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4457 4458 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 4459 @*/ 4460 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4461 { 4462 DM_Plex *mesh = (DM_Plex*) dm->data; 4463 PetscInt *meet[2]; 4464 PetscInt meetSize, i = 0; 4465 PetscInt dof, off, p, c, m; 4466 PetscErrorCode ierr; 4467 4468 PetscFunctionBegin; 4469 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4470 PetscValidPointer(points, 3); 4471 PetscValidPointer(numCoveringPoints, 4); 4472 PetscValidPointer(coveringPoints, 5); 4473 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4474 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4475 /* Copy in cone of first point */ 4476 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 4477 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 4478 for (meetSize = 0; meetSize < dof; ++meetSize) { 4479 meet[i][meetSize] = mesh->cones[off+meetSize]; 4480 } 4481 /* Check each successive cone */ 4482 for (p = 1; p < numPoints; ++p) { 4483 PetscInt newMeetSize = 0; 4484 4485 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 4486 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 4487 for (c = 0; c < dof; ++c) { 4488 const PetscInt point = mesh->cones[off+c]; 4489 4490 for (m = 0; m < meetSize; ++m) { 4491 if (point == meet[i][m]) { 4492 meet[1-i][newMeetSize++] = point; 4493 break; 4494 } 4495 } 4496 } 4497 meetSize = newMeetSize; 4498 i = 1-i; 4499 } 4500 *numCoveringPoints = meetSize; 4501 *coveringPoints = meet[i]; 4502 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4503 PetscFunctionReturn(0); 4504 } 4505 4506 /*@C 4507 DMPlexRestoreMeet - Restore an array for the meet of the set of points 4508 4509 Not Collective 4510 4511 Input Parameters: 4512 + dm - The DMPlex object 4513 . numPoints - The number of input points for the meet 4514 - points - The input points 4515 4516 Output Parameters: 4517 + numCoveredPoints - The number of points in the meet 4518 - coveredPoints - The points in the meet 4519 4520 Level: intermediate 4521 4522 Fortran Notes: 4523 Since it returns an array, this routine is only available in Fortran 90, and you must 4524 include petsc.h90 in your code. 4525 4526 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4527 4528 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 4529 @*/ 4530 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4531 { 4532 PetscErrorCode ierr; 4533 4534 PetscFunctionBegin; 4535 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4536 if (points) PetscValidIntPointer(points,3); 4537 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4538 PetscValidPointer(coveredPoints,5); 4539 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4540 if (numCoveredPoints) *numCoveredPoints = 0; 4541 PetscFunctionReturn(0); 4542 } 4543 4544 /*@C 4545 DMPlexGetFullMeet - Get an array for the meet of the set of points 4546 4547 Not Collective 4548 4549 Input Parameters: 4550 + dm - The DMPlex object 4551 . numPoints - The number of input points for the meet 4552 - points - The input points 4553 4554 Output Parameters: 4555 + numCoveredPoints - The number of points in the meet 4556 - coveredPoints - The points in the meet 4557 4558 Level: intermediate 4559 4560 Fortran Notes: 4561 Since it returns an array, this routine is only available in Fortran 90, and you must 4562 include petsc.h90 in your code. 4563 4564 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4565 4566 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 4567 @*/ 4568 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4569 { 4570 DM_Plex *mesh = (DM_Plex*) dm->data; 4571 PetscInt *offsets, **closures; 4572 PetscInt *meet[2]; 4573 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 4574 PetscInt p, h, c, m, mc; 4575 PetscErrorCode ierr; 4576 4577 PetscFunctionBegin; 4578 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4579 PetscValidPointer(points, 3); 4580 PetscValidPointer(numCoveredPoints, 4); 4581 PetscValidPointer(coveredPoints, 5); 4582 4583 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 4584 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 4585 ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4586 mc = mesh->maxConeSize; 4587 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 4588 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4589 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4590 4591 for (p = 0; p < numPoints; ++p) { 4592 PetscInt closureSize; 4593 4594 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 4595 4596 offsets[p*(height+2)+0] = 0; 4597 for (h = 0; h < height+1; ++h) { 4598 PetscInt pStart, pEnd, i; 4599 4600 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 4601 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4602 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4603 offsets[p*(height+2)+h+1] = i; 4604 break; 4605 } 4606 } 4607 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4608 } 4609 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); 4610 } 4611 for (h = 0; h < height+1; ++h) { 4612 PetscInt dof; 4613 4614 /* Copy in cone of first point */ 4615 dof = offsets[h+1] - offsets[h]; 4616 for (meetSize = 0; meetSize < dof; ++meetSize) { 4617 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4618 } 4619 /* Check each successive cone */ 4620 for (p = 1; p < numPoints && meetSize; ++p) { 4621 PetscInt newMeetSize = 0; 4622 4623 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4624 for (c = 0; c < dof; ++c) { 4625 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4626 4627 for (m = 0; m < meetSize; ++m) { 4628 if (point == meet[i][m]) { 4629 meet[1-i][newMeetSize++] = point; 4630 break; 4631 } 4632 } 4633 } 4634 meetSize = newMeetSize; 4635 i = 1-i; 4636 } 4637 if (meetSize) break; 4638 } 4639 *numCoveredPoints = meetSize; 4640 *coveredPoints = meet[i]; 4641 for (p = 0; p < numPoints; ++p) { 4642 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 4643 } 4644 ierr = PetscFree(closures);CHKERRQ(ierr); 4645 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4646 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4647 PetscFunctionReturn(0); 4648 } 4649 4650 /*@C 4651 DMPlexEqual - Determine if two DMs have the same topology 4652 4653 Not Collective 4654 4655 Input Parameters: 4656 + dmA - A DMPlex object 4657 - dmB - A DMPlex object 4658 4659 Output Parameters: 4660 . equal - PETSC_TRUE if the topologies are identical 4661 4662 Level: intermediate 4663 4664 Notes: 4665 We are not solving graph isomorphism, so we do not permutation. 4666 4667 .seealso: DMPlexGetCone() 4668 @*/ 4669 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 4670 { 4671 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 4672 PetscErrorCode ierr; 4673 4674 PetscFunctionBegin; 4675 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 4676 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4677 PetscValidPointer(equal, 3); 4678 4679 *equal = PETSC_FALSE; 4680 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 4681 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 4682 if (depth != depthB) PetscFunctionReturn(0); 4683 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 4684 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 4685 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 4686 for (p = pStart; p < pEnd; ++p) { 4687 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 4688 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 4689 4690 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 4691 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 4692 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 4693 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 4694 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 4695 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 4696 if (coneSize != coneSizeB) PetscFunctionReturn(0); 4697 for (c = 0; c < coneSize; ++c) { 4698 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 4699 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 4700 } 4701 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 4702 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 4703 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 4704 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 4705 if (supportSize != supportSizeB) PetscFunctionReturn(0); 4706 for (s = 0; s < supportSize; ++s) { 4707 if (support[s] != supportB[s]) PetscFunctionReturn(0); 4708 } 4709 } 4710 *equal = PETSC_TRUE; 4711 PetscFunctionReturn(0); 4712 } 4713 4714 /*@C 4715 DMPlexGetNumFaceVertices - Returns the number of vertices on a face 4716 4717 Not Collective 4718 4719 Input Parameters: 4720 + dm - The DMPlex 4721 . cellDim - The cell dimension 4722 - numCorners - The number of vertices on a cell 4723 4724 Output Parameters: 4725 . numFaceVertices - The number of vertices on a face 4726 4727 Level: developer 4728 4729 Notes: 4730 Of course this can only work for a restricted set of symmetric shapes 4731 4732 .seealso: DMPlexGetCone() 4733 @*/ 4734 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4735 { 4736 MPI_Comm comm; 4737 PetscErrorCode ierr; 4738 4739 PetscFunctionBegin; 4740 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4741 PetscValidPointer(numFaceVertices,4); 4742 switch (cellDim) { 4743 case 0: 4744 *numFaceVertices = 0; 4745 break; 4746 case 1: 4747 *numFaceVertices = 1; 4748 break; 4749 case 2: 4750 switch (numCorners) { 4751 case 3: /* triangle */ 4752 *numFaceVertices = 2; /* Edge has 2 vertices */ 4753 break; 4754 case 4: /* quadrilateral */ 4755 *numFaceVertices = 2; /* Edge has 2 vertices */ 4756 break; 4757 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 4758 *numFaceVertices = 3; /* Edge has 3 vertices */ 4759 break; 4760 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 4761 *numFaceVertices = 3; /* Edge has 3 vertices */ 4762 break; 4763 default: 4764 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4765 } 4766 break; 4767 case 3: 4768 switch (numCorners) { 4769 case 4: /* tetradehdron */ 4770 *numFaceVertices = 3; /* Face has 3 vertices */ 4771 break; 4772 case 6: /* tet cohesive cells */ 4773 *numFaceVertices = 4; /* Face has 4 vertices */ 4774 break; 4775 case 8: /* hexahedron */ 4776 *numFaceVertices = 4; /* Face has 4 vertices */ 4777 break; 4778 case 9: /* tet cohesive Lagrange cells */ 4779 *numFaceVertices = 6; /* Face has 6 vertices */ 4780 break; 4781 case 10: /* quadratic tetrahedron */ 4782 *numFaceVertices = 6; /* Face has 6 vertices */ 4783 break; 4784 case 12: /* hex cohesive Lagrange cells */ 4785 *numFaceVertices = 6; /* Face has 6 vertices */ 4786 break; 4787 case 18: /* quadratic tet cohesive Lagrange cells */ 4788 *numFaceVertices = 6; /* Face has 6 vertices */ 4789 break; 4790 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 4791 *numFaceVertices = 9; /* Face has 9 vertices */ 4792 break; 4793 default: 4794 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4795 } 4796 break; 4797 default: 4798 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 4799 } 4800 PetscFunctionReturn(0); 4801 } 4802 4803 /*@ 4804 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4805 4806 Not Collective 4807 4808 Input Parameter: 4809 . dm - The DMPlex object 4810 4811 Output Parameter: 4812 . depthLabel - The DMLabel recording point depth 4813 4814 Level: developer 4815 4816 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), 4817 @*/ 4818 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4819 { 4820 PetscFunctionBegin; 4821 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4822 PetscValidPointer(depthLabel, 2); 4823 *depthLabel = dm->depthLabel; 4824 PetscFunctionReturn(0); 4825 } 4826 4827 /*@ 4828 DMPlexGetDepth - Get the depth of the DAG representing this mesh 4829 4830 Not Collective 4831 4832 Input Parameter: 4833 . dm - The DMPlex object 4834 4835 Output Parameter: 4836 . depth - The number of strata (breadth first levels) in the DAG 4837 4838 Level: developer 4839 4840 Notes: 4841 This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4842 The point depth is described more in detail in DMPlexGetDepthStratum(). 4843 An empty mesh gives -1. 4844 4845 .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize() 4846 @*/ 4847 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4848 { 4849 DMLabel label; 4850 PetscInt d = 0; 4851 PetscErrorCode ierr; 4852 4853 PetscFunctionBegin; 4854 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4855 PetscValidPointer(depth, 2); 4856 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4857 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 4858 *depth = d-1; 4859 PetscFunctionReturn(0); 4860 } 4861 4862 /*@ 4863 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4864 4865 Not Collective 4866 4867 Input Parameters: 4868 + dm - The DMPlex object 4869 - stratumValue - The requested depth 4870 4871 Output Parameters: 4872 + start - The first point at this depth 4873 - end - One beyond the last point at this depth 4874 4875 Notes: 4876 Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4877 often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4878 higher dimension, e.g., "edges". 4879 4880 Level: developer 4881 4882 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate() 4883 @*/ 4884 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4885 { 4886 DMLabel label; 4887 PetscInt pStart, pEnd; 4888 PetscErrorCode ierr; 4889 4890 PetscFunctionBegin; 4891 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4892 if (start) {PetscValidPointer(start, 3); *start = 0;} 4893 if (end) {PetscValidPointer(end, 4); *end = 0;} 4894 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4895 if (pStart == pEnd) PetscFunctionReturn(0); 4896 if (stratumValue < 0) { 4897 if (start) *start = pStart; 4898 if (end) *end = pEnd; 4899 PetscFunctionReturn(0); 4900 } 4901 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4902 PetscCheckFalse(!label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4903 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 4904 PetscFunctionReturn(0); 4905 } 4906 4907 /*@ 4908 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4909 4910 Not Collective 4911 4912 Input Parameters: 4913 + dm - The DMPlex object 4914 - stratumValue - The requested height 4915 4916 Output Parameters: 4917 + start - The first point at this height 4918 - end - One beyond the last point at this height 4919 4920 Notes: 4921 Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4922 points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4923 stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4924 4925 Level: developer 4926 4927 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight() 4928 @*/ 4929 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4930 { 4931 DMLabel label; 4932 PetscInt depth, pStart, pEnd; 4933 PetscErrorCode ierr; 4934 4935 PetscFunctionBegin; 4936 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4937 if (start) {PetscValidPointer(start, 3); *start = 0;} 4938 if (end) {PetscValidPointer(end, 4); *end = 0;} 4939 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4940 if (pStart == pEnd) PetscFunctionReturn(0); 4941 if (stratumValue < 0) { 4942 if (start) *start = pStart; 4943 if (end) *end = pEnd; 4944 PetscFunctionReturn(0); 4945 } 4946 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4947 PetscCheckFalse(!label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4948 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 4949 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 4950 PetscFunctionReturn(0); 4951 } 4952 4953 /*@ 4954 DMPlexGetPointDepth - Get the depth of a given point 4955 4956 Not Collective 4957 4958 Input Parameters: 4959 + dm - The DMPlex object 4960 - point - The point 4961 4962 Output Parameter: 4963 . depth - The depth of the point 4964 4965 Level: intermediate 4966 4967 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight() 4968 @*/ 4969 PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4970 { 4971 PetscErrorCode ierr; 4972 4973 PetscFunctionBegin; 4974 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4975 PetscValidIntPointer(depth, 3); 4976 ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr); 4977 PetscFunctionReturn(0); 4978 } 4979 4980 /*@ 4981 DMPlexGetPointHeight - Get the height of a given point 4982 4983 Not Collective 4984 4985 Input Parameters: 4986 + dm - The DMPlex object 4987 - point - The point 4988 4989 Output Parameter: 4990 . height - The height of the point 4991 4992 Level: intermediate 4993 4994 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth() 4995 @*/ 4996 PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 4997 { 4998 PetscInt n, pDepth; 4999 PetscErrorCode ierr; 5000 5001 PetscFunctionBegin; 5002 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5003 PetscValidIntPointer(height, 3); 5004 ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr); 5005 ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr); 5006 *height = n - 1 - pDepth; /* DAG depth is n-1 */ 5007 PetscFunctionReturn(0); 5008 } 5009 5010 /*@ 5011 DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 5012 5013 Not Collective 5014 5015 Input Parameter: 5016 . dm - The DMPlex object 5017 5018 Output Parameter: 5019 . celltypeLabel - The DMLabel recording cell polytope type 5020 5021 Note: This function will trigger automatica computation of cell types. This can be disabled by calling 5022 DMCreateLabel(dm, "celltype") beforehand. 5023 5024 Level: developer 5025 5026 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel() 5027 @*/ 5028 PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 5029 { 5030 PetscErrorCode ierr; 5031 5032 PetscFunctionBegin; 5033 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5034 PetscValidPointer(celltypeLabel, 2); 5035 if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);} 5036 *celltypeLabel = dm->celltypeLabel; 5037 PetscFunctionReturn(0); 5038 } 5039 5040 /*@ 5041 DMPlexGetCellType - Get the polytope type of a given cell 5042 5043 Not Collective 5044 5045 Input Parameters: 5046 + dm - The DMPlex object 5047 - cell - The cell 5048 5049 Output Parameter: 5050 . celltype - The polytope type of the cell 5051 5052 Level: intermediate 5053 5054 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth() 5055 @*/ 5056 PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 5057 { 5058 DMLabel label; 5059 PetscInt ct; 5060 PetscErrorCode ierr; 5061 5062 PetscFunctionBegin; 5063 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5064 PetscValidPointer(celltype, 3); 5065 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 5066 ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr); 5067 PetscCheckFalse(ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell); 5068 *celltype = (DMPolytopeType) ct; 5069 PetscFunctionReturn(0); 5070 } 5071 5072 /*@ 5073 DMPlexSetCellType - Set the polytope type of a given cell 5074 5075 Not Collective 5076 5077 Input Parameters: 5078 + dm - The DMPlex object 5079 . cell - The cell 5080 - celltype - The polytope type of the cell 5081 5082 Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 5083 is executed. This function will override the computed type. However, if automatic classification will not succeed 5084 and a user wants to manually specify all types, the classification must be disabled by calling 5085 DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 5086 5087 Level: advanced 5088 5089 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel() 5090 @*/ 5091 PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5092 { 5093 DMLabel label; 5094 PetscErrorCode ierr; 5095 5096 PetscFunctionBegin; 5097 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5098 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 5099 ierr = DMLabelSetValue(label, cell, celltype);CHKERRQ(ierr); 5100 PetscFunctionReturn(0); 5101 } 5102 5103 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 5104 { 5105 PetscSection section, s; 5106 Mat m; 5107 PetscInt maxHeight; 5108 PetscErrorCode ierr; 5109 5110 PetscFunctionBegin; 5111 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 5112 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 5113 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 5114 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 5115 ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr); 5116 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5117 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 5118 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 5119 ierr = DMSetDefaultConstraints(*cdm, s, m, NULL);CHKERRQ(ierr); 5120 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 5121 ierr = MatDestroy(&m);CHKERRQ(ierr); 5122 5123 ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr); 5124 ierr = DMCreateDS(*cdm);CHKERRQ(ierr); 5125 PetscFunctionReturn(0); 5126 } 5127 5128 PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5129 { 5130 Vec coordsLocal; 5131 DM coordsDM; 5132 PetscErrorCode ierr; 5133 5134 PetscFunctionBegin; 5135 *field = NULL; 5136 ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr); 5137 ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr); 5138 if (coordsLocal && coordsDM) { 5139 ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr); 5140 } 5141 PetscFunctionReturn(0); 5142 } 5143 5144 /*@C 5145 DMPlexGetConeSection - Return a section which describes the layout of cone data 5146 5147 Not Collective 5148 5149 Input Parameters: 5150 . dm - The DMPlex object 5151 5152 Output Parameter: 5153 . section - The PetscSection object 5154 5155 Level: developer 5156 5157 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 5158 @*/ 5159 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5160 { 5161 DM_Plex *mesh = (DM_Plex*) dm->data; 5162 5163 PetscFunctionBegin; 5164 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5165 if (section) *section = mesh->coneSection; 5166 PetscFunctionReturn(0); 5167 } 5168 5169 /*@C 5170 DMPlexGetSupportSection - Return a section which describes the layout of support data 5171 5172 Not Collective 5173 5174 Input Parameters: 5175 . dm - The DMPlex object 5176 5177 Output Parameter: 5178 . section - The PetscSection object 5179 5180 Level: developer 5181 5182 .seealso: DMPlexGetConeSection() 5183 @*/ 5184 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5185 { 5186 DM_Plex *mesh = (DM_Plex*) dm->data; 5187 5188 PetscFunctionBegin; 5189 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5190 if (section) *section = mesh->supportSection; 5191 PetscFunctionReturn(0); 5192 } 5193 5194 /*@C 5195 DMPlexGetCones - Return cone data 5196 5197 Not Collective 5198 5199 Input Parameters: 5200 . dm - The DMPlex object 5201 5202 Output Parameter: 5203 . cones - The cone for each point 5204 5205 Level: developer 5206 5207 .seealso: DMPlexGetConeSection() 5208 @*/ 5209 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5210 { 5211 DM_Plex *mesh = (DM_Plex*) dm->data; 5212 5213 PetscFunctionBegin; 5214 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5215 if (cones) *cones = mesh->cones; 5216 PetscFunctionReturn(0); 5217 } 5218 5219 /*@C 5220 DMPlexGetConeOrientations - Return cone orientation data 5221 5222 Not Collective 5223 5224 Input Parameters: 5225 . dm - The DMPlex object 5226 5227 Output Parameter: 5228 . coneOrientations - The array of cone orientations for all points 5229 5230 Level: developer 5231 5232 Notes: 5233 The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation(). 5234 5235 The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation(). 5236 5237 .seealso: DMPlexGetConeSection(), DMPlexGetConeOrientation() 5238 @*/ 5239 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5240 { 5241 DM_Plex *mesh = (DM_Plex*) dm->data; 5242 5243 PetscFunctionBegin; 5244 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5245 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 5246 PetscFunctionReturn(0); 5247 } 5248 5249 /******************************** FEM Support **********************************/ 5250 5251 /* 5252 Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 5253 representing a line in the section. 5254 */ 5255 static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 5256 { 5257 PetscErrorCode ierr; 5258 5259 PetscFunctionBeginHot; 5260 ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr); 5261 if (line < 0) { 5262 *k = 0; 5263 *Nc = 0; 5264 } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 5265 *k = 1; 5266 } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 5267 /* An order k SEM disc has k-1 dofs on an edge */ 5268 ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr); 5269 *k = *k / *Nc + 1; 5270 } 5271 PetscFunctionReturn(0); 5272 } 5273 5274 /*@ 5275 5276 DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5277 lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 5278 section provided (or the section of the DM). 5279 5280 Input Parameters: 5281 + dm - The DM 5282 . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 5283 - section - The PetscSection to reorder, or NULL for the default section 5284 5285 Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5286 degree of the basis. 5287 5288 Example: 5289 A typical interpolated single-quad mesh might order points as 5290 .vb 5291 [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5292 5293 v4 -- e6 -- v3 5294 | | 5295 e7 c0 e8 5296 | | 5297 v1 -- e5 -- v2 5298 .ve 5299 5300 (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5301 dofs in the order of points, e.g., 5302 .vb 5303 c0 -> [0,1,2,3] 5304 v1 -> [4] 5305 ... 5306 e5 -> [8, 9] 5307 .ve 5308 5309 which corresponds to the dofs 5310 .vb 5311 6 10 11 7 5312 13 2 3 15 5313 12 0 1 14 5314 4 8 9 5 5315 .ve 5316 5317 The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5318 .vb 5319 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5320 .ve 5321 5322 After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5323 .vb 5324 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5325 .ve 5326 5327 Level: developer 5328 5329 .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection() 5330 @*/ 5331 PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5332 { 5333 DMLabel label; 5334 PetscInt dim, depth = -1, eStart = -1, Nf; 5335 PetscBool vertexchart; 5336 PetscErrorCode ierr; 5337 5338 PetscFunctionBegin; 5339 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5340 if (dim < 1) PetscFunctionReturn(0); 5341 if (point < 0) { 5342 PetscInt sStart,sEnd; 5343 5344 ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr); 5345 point = sEnd-sStart ? sStart : point; 5346 } 5347 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 5348 if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); } 5349 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5350 if (depth == 1) {eStart = point;} 5351 else if (depth == dim) { 5352 const PetscInt *cone; 5353 5354 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5355 if (dim == 2) eStart = cone[0]; 5356 else if (dim == 3) { 5357 const PetscInt *cone2; 5358 ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 5359 eStart = cone2[0]; 5360 } 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); 5361 } 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); 5362 { /* Determine whether the chart covers all points or just vertices. */ 5363 PetscInt pStart,pEnd,cStart,cEnd; 5364 ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr); 5365 ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr); 5366 if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Only vertices are in the chart */ 5367 else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */ 5368 else vertexchart = PETSC_TRUE; /* Some interpolated points are not in chart; assume dofs only at cells and vertices */ 5369 } 5370 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5371 for (PetscInt d=1; d<=dim; d++) { 5372 PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5373 PetscInt *perm; 5374 5375 for (f = 0; f < Nf; ++f) { 5376 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5377 size += PetscPowInt(k+1, d)*Nc; 5378 } 5379 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 5380 for (f = 0; f < Nf; ++f) { 5381 switch (d) { 5382 case 1: 5383 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5384 /* 5385 Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5386 We want [ vtx0; edge of length k-1; vtx1 ] 5387 */ 5388 for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5389 for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5390 for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5391 foffset = offset; 5392 break; 5393 case 2: 5394 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 5395 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5396 /* The SEM order is 5397 5398 v_lb, {e_b}, v_rb, 5399 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 5400 v_lt, reverse {e_t}, v_rt 5401 */ 5402 { 5403 const PetscInt of = 0; 5404 const PetscInt oeb = of + PetscSqr(k-1); 5405 const PetscInt oer = oeb + (k-1); 5406 const PetscInt oet = oer + (k-1); 5407 const PetscInt oel = oet + (k-1); 5408 const PetscInt ovlb = oel + (k-1); 5409 const PetscInt ovrb = ovlb + 1; 5410 const PetscInt ovrt = ovrb + 1; 5411 const PetscInt ovlt = ovrt + 1; 5412 PetscInt o; 5413 5414 /* bottom */ 5415 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 5416 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5417 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 5418 /* middle */ 5419 for (i = 0; i < k-1; ++i) { 5420 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 5421 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; 5422 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 5423 } 5424 /* top */ 5425 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 5426 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5427 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 5428 foffset = offset; 5429 } 5430 break; 5431 case 3: 5432 /* The original hex closure is 5433 5434 {c, 5435 f_b, f_t, f_f, f_b, f_r, f_l, 5436 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 5437 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 5438 */ 5439 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5440 /* The SEM order is 5441 Bottom Slice 5442 v_blf, {e^{(k-1)-n}_bf}, v_brf, 5443 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 5444 v_blb, {e_bb}, v_brb, 5445 5446 Middle Slice (j) 5447 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 5448 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 5449 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 5450 5451 Top Slice 5452 v_tlf, {e_tf}, v_trf, 5453 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 5454 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 5455 */ 5456 { 5457 const PetscInt oc = 0; 5458 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 5459 const PetscInt oft = ofb + PetscSqr(k-1); 5460 const PetscInt off = oft + PetscSqr(k-1); 5461 const PetscInt ofk = off + PetscSqr(k-1); 5462 const PetscInt ofr = ofk + PetscSqr(k-1); 5463 const PetscInt ofl = ofr + PetscSqr(k-1); 5464 const PetscInt oebl = ofl + PetscSqr(k-1); 5465 const PetscInt oebb = oebl + (k-1); 5466 const PetscInt oebr = oebb + (k-1); 5467 const PetscInt oebf = oebr + (k-1); 5468 const PetscInt oetf = oebf + (k-1); 5469 const PetscInt oetr = oetf + (k-1); 5470 const PetscInt oetb = oetr + (k-1); 5471 const PetscInt oetl = oetb + (k-1); 5472 const PetscInt oerf = oetl + (k-1); 5473 const PetscInt oelf = oerf + (k-1); 5474 const PetscInt oelb = oelf + (k-1); 5475 const PetscInt oerb = oelb + (k-1); 5476 const PetscInt ovblf = oerb + (k-1); 5477 const PetscInt ovblb = ovblf + 1; 5478 const PetscInt ovbrb = ovblb + 1; 5479 const PetscInt ovbrf = ovbrb + 1; 5480 const PetscInt ovtlf = ovbrf + 1; 5481 const PetscInt ovtrf = ovtlf + 1; 5482 const PetscInt ovtrb = ovtrf + 1; 5483 const PetscInt ovtlb = ovtrb + 1; 5484 PetscInt o, n; 5485 5486 /* Bottom Slice */ 5487 /* bottom */ 5488 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 5489 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5490 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 5491 /* middle */ 5492 for (i = 0; i < k-1; ++i) { 5493 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5494 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;} 5495 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 5496 } 5497 /* top */ 5498 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 5499 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5500 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 5501 5502 /* Middle Slice */ 5503 for (j = 0; j < k-1; ++j) { 5504 /* bottom */ 5505 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 5506 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; 5507 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 5508 /* middle */ 5509 for (i = 0; i < k-1; ++i) { 5510 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 5511 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; 5512 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 5513 } 5514 /* top */ 5515 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 5516 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; 5517 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 5518 } 5519 5520 /* Top Slice */ 5521 /* bottom */ 5522 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 5523 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5524 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 5525 /* middle */ 5526 for (i = 0; i < k-1; ++i) { 5527 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 5528 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 5529 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 5530 } 5531 /* top */ 5532 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 5533 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5534 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 5535 5536 foffset = offset; 5537 } 5538 break; 5539 default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d); 5540 } 5541 } 5542 PetscCheckFalse(offset != size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 5543 /* Check permutation */ 5544 { 5545 PetscInt *check; 5546 5547 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 5548 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]);} 5549 for (i = 0; i < size; ++i) check[perm[i]] = i; 5550 for (i = 0; i < size; ++i) {PetscCheckFalse(check[i] < 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 5551 ierr = PetscFree(check);CHKERRQ(ierr); 5552 } 5553 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 5554 if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 5555 PetscInt *loc_perm; 5556 ierr = PetscMalloc1(size*2, &loc_perm);CHKERRQ(ierr); 5557 for (PetscInt i=0; i<size; i++) { 5558 loc_perm[i] = perm[i]; 5559 loc_perm[size+i] = size + perm[i]; 5560 } 5561 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm);CHKERRQ(ierr); 5562 } 5563 } 5564 PetscFunctionReturn(0); 5565 } 5566 5567 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5568 { 5569 PetscDS prob; 5570 PetscInt depth, Nf, h; 5571 DMLabel label; 5572 PetscErrorCode ierr; 5573 5574 PetscFunctionBeginHot; 5575 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 5576 Nf = prob->Nf; 5577 label = dm->depthLabel; 5578 *dspace = NULL; 5579 if (field < Nf) { 5580 PetscObject disc = prob->disc[field]; 5581 5582 if (disc->classid == PETSCFE_CLASSID) { 5583 PetscDualSpace dsp; 5584 5585 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 5586 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 5587 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 5588 h = depth - 1 - h; 5589 if (h) { 5590 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 5591 } else { 5592 *dspace = dsp; 5593 } 5594 } 5595 } 5596 PetscFunctionReturn(0); 5597 } 5598 5599 static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5600 { 5601 PetscScalar *array, *vArray; 5602 const PetscInt *cone, *coneO; 5603 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5604 PetscErrorCode ierr; 5605 5606 PetscFunctionBeginHot; 5607 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5608 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5609 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5610 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5611 if (!values || !*values) { 5612 if ((point >= pStart) && (point < pEnd)) { 5613 PetscInt dof; 5614 5615 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5616 size += dof; 5617 } 5618 for (p = 0; p < numPoints; ++p) { 5619 const PetscInt cp = cone[p]; 5620 PetscInt dof; 5621 5622 if ((cp < pStart) || (cp >= pEnd)) continue; 5623 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5624 size += dof; 5625 } 5626 if (!values) { 5627 if (csize) *csize = size; 5628 PetscFunctionReturn(0); 5629 } 5630 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 5631 } else { 5632 array = *values; 5633 } 5634 size = 0; 5635 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 5636 if ((point >= pStart) && (point < pEnd)) { 5637 PetscInt dof, off, d; 5638 PetscScalar *varr; 5639 5640 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5641 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5642 varr = &vArray[off]; 5643 for (d = 0; d < dof; ++d, ++offset) { 5644 array[offset] = varr[d]; 5645 } 5646 size += dof; 5647 } 5648 for (p = 0; p < numPoints; ++p) { 5649 const PetscInt cp = cone[p]; 5650 PetscInt o = coneO[p]; 5651 PetscInt dof, off, d; 5652 PetscScalar *varr; 5653 5654 if ((cp < pStart) || (cp >= pEnd)) continue; 5655 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5656 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 5657 varr = &vArray[off]; 5658 if (o >= 0) { 5659 for (d = 0; d < dof; ++d, ++offset) { 5660 array[offset] = varr[d]; 5661 } 5662 } else { 5663 for (d = dof-1; d >= 0; --d, ++offset) { 5664 array[offset] = varr[d]; 5665 } 5666 } 5667 size += dof; 5668 } 5669 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 5670 if (!*values) { 5671 if (csize) *csize = size; 5672 *values = array; 5673 } else { 5674 PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5675 *csize = size; 5676 } 5677 PetscFunctionReturn(0); 5678 } 5679 5680 /* Compress out points not in the section */ 5681 static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 5682 { 5683 const PetscInt np = *numPoints; 5684 PetscInt pStart, pEnd, p, q; 5685 PetscErrorCode ierr; 5686 5687 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5688 for (p = 0, q = 0; p < np; ++p) { 5689 const PetscInt r = points[p*2]; 5690 if ((r >= pStart) && (r < pEnd)) { 5691 points[q*2] = r; 5692 points[q*2+1] = points[p*2+1]; 5693 ++q; 5694 } 5695 } 5696 *numPoints = q; 5697 return 0; 5698 } 5699 5700 /* Compressed closure does not apply closure permutation */ 5701 PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5702 { 5703 const PetscInt *cla = NULL; 5704 PetscInt np, *pts = NULL; 5705 PetscErrorCode ierr; 5706 5707 PetscFunctionBeginHot; 5708 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 5709 if (*clPoints) { 5710 PetscInt dof, off; 5711 5712 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 5713 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 5714 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 5715 np = dof/2; 5716 pts = (PetscInt *) &cla[off]; 5717 } else { 5718 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 5719 ierr = CompressPoints_Private(section, &np, pts);CHKERRQ(ierr); 5720 } 5721 *numPoints = np; 5722 *points = pts; 5723 *clp = cla; 5724 PetscFunctionReturn(0); 5725 } 5726 5727 PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5728 { 5729 PetscErrorCode ierr; 5730 5731 PetscFunctionBeginHot; 5732 if (!*clPoints) { 5733 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 5734 } else { 5735 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 5736 } 5737 *numPoints = 0; 5738 *points = NULL; 5739 *clSec = NULL; 5740 *clPoints = NULL; 5741 *clp = NULL; 5742 PetscFunctionReturn(0); 5743 } 5744 5745 static inline PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 5746 { 5747 PetscInt offset = 0, p; 5748 const PetscInt **perms = NULL; 5749 const PetscScalar **flips = NULL; 5750 PetscErrorCode ierr; 5751 5752 PetscFunctionBeginHot; 5753 *size = 0; 5754 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5755 for (p = 0; p < numPoints; p++) { 5756 const PetscInt point = points[2*p]; 5757 const PetscInt *perm = perms ? perms[p] : NULL; 5758 const PetscScalar *flip = flips ? flips[p] : NULL; 5759 PetscInt dof, off, d; 5760 const PetscScalar *varr; 5761 5762 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5763 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5764 varr = &vArray[off]; 5765 if (clperm) { 5766 if (perm) { 5767 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 5768 } else { 5769 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 5770 } 5771 if (flip) { 5772 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 5773 } 5774 } else { 5775 if (perm) { 5776 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 5777 } else { 5778 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 5779 } 5780 if (flip) { 5781 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 5782 } 5783 } 5784 offset += dof; 5785 } 5786 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5787 *size = offset; 5788 PetscFunctionReturn(0); 5789 } 5790 5791 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[]) 5792 { 5793 PetscInt offset = 0, f; 5794 PetscErrorCode ierr; 5795 5796 PetscFunctionBeginHot; 5797 *size = 0; 5798 for (f = 0; f < numFields; ++f) { 5799 PetscInt p; 5800 const PetscInt **perms = NULL; 5801 const PetscScalar **flips = NULL; 5802 5803 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5804 for (p = 0; p < numPoints; p++) { 5805 const PetscInt point = points[2*p]; 5806 PetscInt fdof, foff, b; 5807 const PetscScalar *varr; 5808 const PetscInt *perm = perms ? perms[p] : NULL; 5809 const PetscScalar *flip = flips ? flips[p] : NULL; 5810 5811 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5812 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5813 varr = &vArray[foff]; 5814 if (clperm) { 5815 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 5816 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 5817 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 5818 } else { 5819 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 5820 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 5821 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 5822 } 5823 offset += fdof; 5824 } 5825 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5826 } 5827 *size = offset; 5828 PetscFunctionReturn(0); 5829 } 5830 5831 /*@C 5832 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5833 5834 Not collective 5835 5836 Input Parameters: 5837 + dm - The DM 5838 . section - The section describing the layout in v, or NULL to use the default section 5839 . v - The local vector 5840 - point - The point in the DM 5841 5842 Input/Output Parameters: 5843 + csize - The size of the input values array, or NULL; on output the number of values in the closure 5844 - values - An array to use for the values, or NULL to have it allocated automatically; 5845 if the user provided NULL, it is a borrowed array and should not be freed 5846 5847 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 5848 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 5849 $ assembly function, and a user may already have allocated storage for this operation. 5850 $ 5851 $ A typical use could be 5852 $ 5853 $ values = NULL; 5854 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5855 $ for (cl = 0; cl < clSize; ++cl) { 5856 $ <Compute on closure> 5857 $ } 5858 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5859 $ 5860 $ or 5861 $ 5862 $ PetscMalloc1(clMaxSize, &values); 5863 $ for (p = pStart; p < pEnd; ++p) { 5864 $ clSize = clMaxSize; 5865 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5866 $ for (cl = 0; cl < clSize; ++cl) { 5867 $ <Compute on closure> 5868 $ } 5869 $ } 5870 $ PetscFree(values); 5871 5872 Fortran Notes: 5873 Since it returns an array, this routine is only available in Fortran 90, and you must 5874 include petsc.h90 in your code. 5875 5876 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5877 5878 Level: intermediate 5879 5880 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5881 @*/ 5882 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5883 { 5884 PetscSection clSection; 5885 IS clPoints; 5886 PetscInt *points = NULL; 5887 const PetscInt *clp, *perm; 5888 PetscInt depth, numFields, numPoints, asize; 5889 PetscErrorCode ierr; 5890 5891 PetscFunctionBeginHot; 5892 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5893 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5894 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5895 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5896 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5897 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5898 if (depth == 1 && numFields < 2) { 5899 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5900 PetscFunctionReturn(0); 5901 } 5902 /* Get points */ 5903 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5904 /* Get sizes */ 5905 asize = 0; 5906 for (PetscInt p = 0; p < numPoints*2; p += 2) { 5907 PetscInt dof; 5908 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5909 asize += dof; 5910 } 5911 if (values) { 5912 const PetscScalar *vArray; 5913 PetscInt size; 5914 5915 if (*values) { 5916 PetscCheckFalse(*csize < asize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %D not sufficient to hold closure size %D", *csize, asize); 5917 } else {ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, values);CHKERRQ(ierr);} 5918 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm);CHKERRQ(ierr); 5919 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5920 /* Get values */ 5921 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values);CHKERRQ(ierr);} 5922 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values);CHKERRQ(ierr);} 5923 PetscCheckFalse(asize != size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size); 5924 /* Cleanup array */ 5925 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5926 } 5927 if (csize) *csize = asize; 5928 /* Cleanup points */ 5929 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5930 PetscFunctionReturn(0); 5931 } 5932 5933 PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5934 { 5935 DMLabel depthLabel; 5936 PetscSection clSection; 5937 IS clPoints; 5938 PetscScalar *array; 5939 const PetscScalar *vArray; 5940 PetscInt *points = NULL; 5941 const PetscInt *clp, *perm = NULL; 5942 PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5943 PetscErrorCode ierr; 5944 5945 PetscFunctionBeginHot; 5946 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5947 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5948 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5949 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5950 ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr); 5951 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 5952 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5953 if (mdepth == 1 && numFields < 2) { 5954 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5955 PetscFunctionReturn(0); 5956 } 5957 /* Get points */ 5958 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5959 for (clsize=0,p=0; p<Np; p++) { 5960 PetscInt dof; 5961 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 5962 clsize += dof; 5963 } 5964 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm);CHKERRQ(ierr); 5965 /* Filter points */ 5966 for (p = 0; p < numPoints*2; p += 2) { 5967 PetscInt dep; 5968 5969 ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr); 5970 if (dep != depth) continue; 5971 points[Np*2+0] = points[p]; 5972 points[Np*2+1] = points[p+1]; 5973 ++Np; 5974 } 5975 /* Get array */ 5976 if (!values || !*values) { 5977 PetscInt asize = 0, dof; 5978 5979 for (p = 0; p < Np*2; p += 2) { 5980 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5981 asize += dof; 5982 } 5983 if (!values) { 5984 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5985 if (csize) *csize = asize; 5986 PetscFunctionReturn(0); 5987 } 5988 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 5989 } else { 5990 array = *values; 5991 } 5992 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5993 /* Get values */ 5994 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 5995 else {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);} 5996 /* Cleanup points */ 5997 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5998 /* Cleanup array */ 5999 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 6000 if (!*values) { 6001 if (csize) *csize = size; 6002 *values = array; 6003 } else { 6004 PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 6005 *csize = size; 6006 } 6007 PetscFunctionReturn(0); 6008 } 6009 6010 /*@C 6011 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6012 6013 Not collective 6014 6015 Input Parameters: 6016 + dm - The DM 6017 . section - The section describing the layout in v, or NULL to use the default section 6018 . v - The local vector 6019 . point - The point in the DM 6020 . csize - The number of values in the closure, or NULL 6021 - values - The array of values, which is a borrowed array and should not be freed 6022 6023 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 6024 6025 Fortran Notes: 6026 Since it returns an array, this routine is only available in Fortran 90, and you must 6027 include petsc.h90 in your code. 6028 6029 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 6030 6031 Level: intermediate 6032 6033 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 6034 @*/ 6035 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6036 { 6037 PetscInt size = 0; 6038 PetscErrorCode ierr; 6039 6040 PetscFunctionBegin; 6041 /* Should work without recalculating size */ 6042 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 6043 *values = NULL; 6044 PetscFunctionReturn(0); 6045 } 6046 6047 static inline void add (PetscScalar *x, PetscScalar y) {*x += y;} 6048 static inline void insert(PetscScalar *x, PetscScalar y) {*x = y;} 6049 6050 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[]) 6051 { 6052 PetscInt cdof; /* The number of constraints on this point */ 6053 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6054 PetscScalar *a; 6055 PetscInt off, cind = 0, k; 6056 PetscErrorCode ierr; 6057 6058 PetscFunctionBegin; 6059 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6060 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6061 a = &array[off]; 6062 if (!cdof || setBC) { 6063 if (clperm) { 6064 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 6065 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 6066 } else { 6067 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 6068 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 6069 } 6070 } else { 6071 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6072 if (clperm) { 6073 if (perm) {for (k = 0; k < dof; ++k) { 6074 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6075 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6076 } 6077 } else { 6078 for (k = 0; k < dof; ++k) { 6079 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6080 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 6081 } 6082 } 6083 } else { 6084 if (perm) { 6085 for (k = 0; k < dof; ++k) { 6086 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6087 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 6088 } 6089 } else { 6090 for (k = 0; k < dof; ++k) { 6091 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6092 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 6093 } 6094 } 6095 } 6096 } 6097 PetscFunctionReturn(0); 6098 } 6099 6100 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[]) 6101 { 6102 PetscInt cdof; /* The number of constraints on this point */ 6103 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6104 PetscScalar *a; 6105 PetscInt off, cind = 0, k; 6106 PetscErrorCode ierr; 6107 6108 PetscFunctionBegin; 6109 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6110 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 6111 a = &array[off]; 6112 if (cdof) { 6113 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6114 if (clperm) { 6115 if (perm) { 6116 for (k = 0; k < dof; ++k) { 6117 if ((cind < cdof) && (k == cdofs[cind])) { 6118 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6119 cind++; 6120 } 6121 } 6122 } else { 6123 for (k = 0; k < dof; ++k) { 6124 if ((cind < cdof) && (k == cdofs[cind])) { 6125 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 6126 cind++; 6127 } 6128 } 6129 } 6130 } else { 6131 if (perm) { 6132 for (k = 0; k < dof; ++k) { 6133 if ((cind < cdof) && (k == cdofs[cind])) { 6134 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 6135 cind++; 6136 } 6137 } 6138 } else { 6139 for (k = 0; k < dof; ++k) { 6140 if ((cind < cdof) && (k == cdofs[cind])) { 6141 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 6142 cind++; 6143 } 6144 } 6145 } 6146 } 6147 } 6148 PetscFunctionReturn(0); 6149 } 6150 6151 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[]) 6152 { 6153 PetscScalar *a; 6154 PetscInt fdof, foff, fcdof, foffset = *offset; 6155 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6156 PetscInt cind = 0, b; 6157 PetscErrorCode ierr; 6158 6159 PetscFunctionBegin; 6160 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6161 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6162 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 6163 a = &array[foff]; 6164 if (!fcdof || setBC) { 6165 if (clperm) { 6166 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 6167 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 6168 } else { 6169 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 6170 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 6171 } 6172 } else { 6173 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6174 if (clperm) { 6175 if (perm) { 6176 for (b = 0; b < fdof; b++) { 6177 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6178 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6179 } 6180 } else { 6181 for (b = 0; b < fdof; b++) { 6182 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6183 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6184 } 6185 } 6186 } else { 6187 if (perm) { 6188 for (b = 0; b < fdof; b++) { 6189 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6190 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6191 } 6192 } else { 6193 for (b = 0; b < fdof; b++) { 6194 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6195 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6196 } 6197 } 6198 } 6199 } 6200 *offset += fdof; 6201 PetscFunctionReturn(0); 6202 } 6203 6204 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[]) 6205 { 6206 PetscScalar *a; 6207 PetscInt fdof, foff, fcdof, foffset = *offset; 6208 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6209 PetscInt Nc, cind = 0, ncind = 0, b; 6210 PetscBool ncSet, fcSet; 6211 PetscErrorCode ierr; 6212 6213 PetscFunctionBegin; 6214 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 6215 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6216 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6217 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 6218 a = &array[foff]; 6219 if (fcdof) { 6220 /* We just override fcdof and fcdofs with Ncc and comps */ 6221 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6222 if (clperm) { 6223 if (perm) { 6224 if (comps) { 6225 for (b = 0; b < fdof; b++) { 6226 ncSet = fcSet = PETSC_FALSE; 6227 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6228 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6229 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 6230 } 6231 } else { 6232 for (b = 0; b < fdof; b++) { 6233 if ((cind < fcdof) && (b == fcdofs[cind])) { 6234 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6235 ++cind; 6236 } 6237 } 6238 } 6239 } else { 6240 if (comps) { 6241 for (b = 0; b < fdof; b++) { 6242 ncSet = fcSet = PETSC_FALSE; 6243 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6244 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6245 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 6246 } 6247 } else { 6248 for (b = 0; b < fdof; b++) { 6249 if ((cind < fcdof) && (b == fcdofs[cind])) { 6250 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6251 ++cind; 6252 } 6253 } 6254 } 6255 } 6256 } else { 6257 if (perm) { 6258 if (comps) { 6259 for (b = 0; b < fdof; b++) { 6260 ncSet = fcSet = PETSC_FALSE; 6261 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6262 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6263 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 6264 } 6265 } else { 6266 for (b = 0; b < fdof; b++) { 6267 if ((cind < fcdof) && (b == fcdofs[cind])) { 6268 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6269 ++cind; 6270 } 6271 } 6272 } 6273 } else { 6274 if (comps) { 6275 for (b = 0; b < fdof; b++) { 6276 ncSet = fcSet = PETSC_FALSE; 6277 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6278 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6279 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 6280 } 6281 } else { 6282 for (b = 0; b < fdof; b++) { 6283 if ((cind < fcdof) && (b == fcdofs[cind])) { 6284 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6285 ++cind; 6286 } 6287 } 6288 } 6289 } 6290 } 6291 } 6292 *offset += fdof; 6293 PetscFunctionReturn(0); 6294 } 6295 6296 static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6297 { 6298 PetscScalar *array; 6299 const PetscInt *cone, *coneO; 6300 PetscInt pStart, pEnd, p, numPoints, off, dof; 6301 PetscErrorCode ierr; 6302 6303 PetscFunctionBeginHot; 6304 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6305 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 6306 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 6307 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 6308 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6309 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6310 const PetscInt cp = !p ? point : cone[p-1]; 6311 const PetscInt o = !p ? 0 : coneO[p-1]; 6312 6313 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 6314 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 6315 /* ADD_VALUES */ 6316 { 6317 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6318 PetscScalar *a; 6319 PetscInt cdof, coff, cind = 0, k; 6320 6321 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 6322 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 6323 a = &array[coff]; 6324 if (!cdof) { 6325 if (o >= 0) { 6326 for (k = 0; k < dof; ++k) { 6327 a[k] += values[off+k]; 6328 } 6329 } else { 6330 for (k = 0; k < dof; ++k) { 6331 a[k] += values[off+dof-k-1]; 6332 } 6333 } 6334 } else { 6335 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 6336 if (o >= 0) { 6337 for (k = 0; k < dof; ++k) { 6338 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6339 a[k] += values[off+k]; 6340 } 6341 } else { 6342 for (k = 0; k < dof; ++k) { 6343 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6344 a[k] += values[off+dof-k-1]; 6345 } 6346 } 6347 } 6348 } 6349 } 6350 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6351 PetscFunctionReturn(0); 6352 } 6353 6354 /*@C 6355 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6356 6357 Not collective 6358 6359 Input Parameters: 6360 + dm - The DM 6361 . section - The section describing the layout in v, or NULL to use the default section 6362 . v - The local vector 6363 . point - The point in the DM 6364 . values - The array of values 6365 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 6366 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 6367 6368 Fortran Notes: 6369 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6370 6371 Level: intermediate 6372 6373 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6374 @*/ 6375 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6376 { 6377 PetscSection clSection; 6378 IS clPoints; 6379 PetscScalar *array; 6380 PetscInt *points = NULL; 6381 const PetscInt *clp, *clperm = NULL; 6382 PetscInt depth, numFields, numPoints, p, clsize; 6383 PetscErrorCode ierr; 6384 6385 PetscFunctionBeginHot; 6386 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6387 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6388 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6389 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6390 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6391 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6392 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 6393 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 6394 PetscFunctionReturn(0); 6395 } 6396 /* Get points */ 6397 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6398 for (clsize=0,p=0; p<numPoints; p++) { 6399 PetscInt dof; 6400 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 6401 clsize += dof; 6402 } 6403 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 6404 /* Get array */ 6405 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6406 /* Get values */ 6407 if (numFields > 0) { 6408 PetscInt offset = 0, f; 6409 for (f = 0; f < numFields; ++f) { 6410 const PetscInt **perms = NULL; 6411 const PetscScalar **flips = NULL; 6412 6413 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6414 switch (mode) { 6415 case INSERT_VALUES: 6416 for (p = 0; p < numPoints; p++) { 6417 const PetscInt point = points[2*p]; 6418 const PetscInt *perm = perms ? perms[p] : NULL; 6419 const PetscScalar *flip = flips ? flips[p] : NULL; 6420 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6421 } break; 6422 case INSERT_ALL_VALUES: 6423 for (p = 0; p < numPoints; p++) { 6424 const PetscInt point = points[2*p]; 6425 const PetscInt *perm = perms ? perms[p] : NULL; 6426 const PetscScalar *flip = flips ? flips[p] : NULL; 6427 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6428 } break; 6429 case INSERT_BC_VALUES: 6430 for (p = 0; p < numPoints; p++) { 6431 const PetscInt point = points[2*p]; 6432 const PetscInt *perm = perms ? perms[p] : NULL; 6433 const PetscScalar *flip = flips ? flips[p] : NULL; 6434 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6435 } break; 6436 case ADD_VALUES: 6437 for (p = 0; p < numPoints; p++) { 6438 const PetscInt point = points[2*p]; 6439 const PetscInt *perm = perms ? perms[p] : NULL; 6440 const PetscScalar *flip = flips ? flips[p] : NULL; 6441 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6442 } break; 6443 case ADD_ALL_VALUES: 6444 for (p = 0; p < numPoints; p++) { 6445 const PetscInt point = points[2*p]; 6446 const PetscInt *perm = perms ? perms[p] : NULL; 6447 const PetscScalar *flip = flips ? flips[p] : NULL; 6448 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6449 } break; 6450 case ADD_BC_VALUES: 6451 for (p = 0; p < numPoints; p++) { 6452 const PetscInt point = points[2*p]; 6453 const PetscInt *perm = perms ? perms[p] : NULL; 6454 const PetscScalar *flip = flips ? flips[p] : NULL; 6455 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6456 } break; 6457 default: 6458 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6459 } 6460 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6461 } 6462 } else { 6463 PetscInt dof, off; 6464 const PetscInt **perms = NULL; 6465 const PetscScalar **flips = NULL; 6466 6467 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6468 switch (mode) { 6469 case INSERT_VALUES: 6470 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6471 const PetscInt point = points[2*p]; 6472 const PetscInt *perm = perms ? perms[p] : NULL; 6473 const PetscScalar *flip = flips ? flips[p] : NULL; 6474 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6475 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6476 } break; 6477 case INSERT_ALL_VALUES: 6478 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6479 const PetscInt point = points[2*p]; 6480 const PetscInt *perm = perms ? perms[p] : NULL; 6481 const PetscScalar *flip = flips ? flips[p] : NULL; 6482 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6483 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6484 } break; 6485 case INSERT_BC_VALUES: 6486 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6487 const PetscInt point = points[2*p]; 6488 const PetscInt *perm = perms ? perms[p] : NULL; 6489 const PetscScalar *flip = flips ? flips[p] : NULL; 6490 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6491 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6492 } break; 6493 case ADD_VALUES: 6494 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6495 const PetscInt point = points[2*p]; 6496 const PetscInt *perm = perms ? perms[p] : NULL; 6497 const PetscScalar *flip = flips ? flips[p] : NULL; 6498 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6499 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6500 } break; 6501 case ADD_ALL_VALUES: 6502 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6503 const PetscInt point = points[2*p]; 6504 const PetscInt *perm = perms ? perms[p] : NULL; 6505 const PetscScalar *flip = flips ? flips[p] : NULL; 6506 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6507 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6508 } break; 6509 case ADD_BC_VALUES: 6510 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6511 const PetscInt point = points[2*p]; 6512 const PetscInt *perm = perms ? perms[p] : NULL; 6513 const PetscScalar *flip = flips ? flips[p] : NULL; 6514 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6515 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6516 } break; 6517 default: 6518 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6519 } 6520 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6521 } 6522 /* Cleanup points */ 6523 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6524 /* Cleanup array */ 6525 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6526 PetscFunctionReturn(0); 6527 } 6528 6529 /* Check whether the given point is in the label. If not, update the offset to skip this point */ 6530 static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 6531 { 6532 PetscFunctionBegin; 6533 if (label) { 6534 PetscInt val, fdof; 6535 PetscErrorCode ierr; 6536 6537 /* There is a problem with this: 6538 Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that 6539 touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell. 6540 Thus I am only going to check val != -1, not val != labelId 6541 */ 6542 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 6543 if (val < 0) { 6544 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6545 *offset += fdof; 6546 PetscFunctionReturn(1); 6547 } 6548 } 6549 PetscFunctionReturn(0); 6550 } 6551 6552 /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 6553 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) 6554 { 6555 PetscSection clSection; 6556 IS clPoints; 6557 PetscScalar *array; 6558 PetscInt *points = NULL; 6559 const PetscInt *clp; 6560 PetscInt numFields, numPoints, p; 6561 PetscInt offset = 0, f; 6562 PetscErrorCode ierr; 6563 6564 PetscFunctionBeginHot; 6565 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6566 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6567 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6568 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6569 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6570 /* Get points */ 6571 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6572 /* Get array */ 6573 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6574 /* Get values */ 6575 for (f = 0; f < numFields; ++f) { 6576 const PetscInt **perms = NULL; 6577 const PetscScalar **flips = NULL; 6578 6579 if (!fieldActive[f]) { 6580 for (p = 0; p < numPoints*2; p += 2) { 6581 PetscInt fdof; 6582 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6583 offset += fdof; 6584 } 6585 continue; 6586 } 6587 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6588 switch (mode) { 6589 case INSERT_VALUES: 6590 for (p = 0; p < numPoints; p++) { 6591 const PetscInt point = points[2*p]; 6592 const PetscInt *perm = perms ? perms[p] : NULL; 6593 const PetscScalar *flip = flips ? flips[p] : NULL; 6594 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6595 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array); 6596 } break; 6597 case INSERT_ALL_VALUES: 6598 for (p = 0; p < numPoints; p++) { 6599 const PetscInt point = points[2*p]; 6600 const PetscInt *perm = perms ? perms[p] : NULL; 6601 const PetscScalar *flip = flips ? flips[p] : NULL; 6602 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6603 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array); 6604 } break; 6605 case INSERT_BC_VALUES: 6606 for (p = 0; p < numPoints; p++) { 6607 const PetscInt point = points[2*p]; 6608 const PetscInt *perm = perms ? perms[p] : NULL; 6609 const PetscScalar *flip = flips ? flips[p] : NULL; 6610 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6611 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array); 6612 } break; 6613 case ADD_VALUES: 6614 for (p = 0; p < numPoints; p++) { 6615 const PetscInt point = points[2*p]; 6616 const PetscInt *perm = perms ? perms[p] : NULL; 6617 const PetscScalar *flip = flips ? flips[p] : NULL; 6618 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6619 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array); 6620 } break; 6621 case ADD_ALL_VALUES: 6622 for (p = 0; p < numPoints; p++) { 6623 const PetscInt point = points[2*p]; 6624 const PetscInt *perm = perms ? perms[p] : NULL; 6625 const PetscScalar *flip = flips ? flips[p] : NULL; 6626 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6627 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array); 6628 } break; 6629 default: 6630 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6631 } 6632 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6633 } 6634 /* Cleanup points */ 6635 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6636 /* Cleanup array */ 6637 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6638 PetscFunctionReturn(0); 6639 } 6640 6641 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6642 { 6643 PetscMPIInt rank; 6644 PetscInt i, j; 6645 PetscErrorCode ierr; 6646 6647 PetscFunctionBegin; 6648 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr); 6649 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 6650 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 6651 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 6652 numCIndices = numCIndices ? numCIndices : numRIndices; 6653 if (!values) PetscFunctionReturn(0); 6654 for (i = 0; i < numRIndices; i++) { 6655 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 6656 for (j = 0; j < numCIndices; j++) { 6657 #if defined(PETSC_USE_COMPLEX) 6658 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 6659 #else 6660 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 6661 #endif 6662 } 6663 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6664 } 6665 PetscFunctionReturn(0); 6666 } 6667 6668 /* 6669 DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 6670 6671 Input Parameters: 6672 + section - The section for this data layout 6673 . islocal - Is the section (and thus indices being requested) local or global? 6674 . point - The point contributing dofs with these indices 6675 . off - The global offset of this point 6676 . loff - The local offset of each field 6677 . setBC - The flag determining whether to include indices of boundary values 6678 . perm - A permutation of the dofs on this point, or NULL 6679 - indperm - A permutation of the entire indices array, or NULL 6680 6681 Output Parameter: 6682 . indices - Indices for dofs on this point 6683 6684 Level: developer 6685 6686 Note: The indices could be local or global, depending on the value of 'off'. 6687 */ 6688 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6689 { 6690 PetscInt dof; /* The number of unknowns on this point */ 6691 PetscInt cdof; /* The number of constraints on this point */ 6692 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6693 PetscInt cind = 0, k; 6694 PetscErrorCode ierr; 6695 6696 PetscFunctionBegin; 6697 PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6698 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6699 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6700 if (!cdof || setBC) { 6701 for (k = 0; k < dof; ++k) { 6702 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6703 const PetscInt ind = indperm ? indperm[preind] : preind; 6704 6705 indices[ind] = off + k; 6706 } 6707 } else { 6708 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6709 for (k = 0; k < dof; ++k) { 6710 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6711 const PetscInt ind = indperm ? indperm[preind] : preind; 6712 6713 if ((cind < cdof) && (k == cdofs[cind])) { 6714 /* Insert check for returning constrained indices */ 6715 indices[ind] = -(off+k+1); 6716 ++cind; 6717 } else { 6718 indices[ind] = off + k - (islocal ? 0 : cind); 6719 } 6720 } 6721 } 6722 *loff += dof; 6723 PetscFunctionReturn(0); 6724 } 6725 6726 /* 6727 DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 6728 6729 Input Parameters: 6730 + section - a section (global or local) 6731 - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 6732 . point - point within section 6733 . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 6734 . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 6735 . setBC - identify constrained (boundary condition) points via involution. 6736 . perms - perms[f][permsoff][:] is a permutation of dofs within each field 6737 . permsoff - offset 6738 - indperm - index permutation 6739 6740 Output Parameter: 6741 . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 6742 . indices - array to hold indices (as defined by section) of each dof associated with point 6743 6744 Notes: 6745 If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 6746 If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 6747 in the local vector. 6748 6749 If section is global and setBC=false, the indices for constrained points are negative (and their value is not 6750 significant). It is invalid to call with a global section and setBC=true. 6751 6752 Developer Note: 6753 The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 6754 in the future, global sections may have fields set, in which case we could pass the global section and obtain the 6755 offset could be obtained from the section instead of passing it explicitly as we do now. 6756 6757 Example: 6758 Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 6759 When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 6760 Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 6761 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. 6762 6763 Level: developer 6764 */ 6765 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[]) 6766 { 6767 PetscInt numFields, foff, f; 6768 PetscErrorCode ierr; 6769 6770 PetscFunctionBegin; 6771 PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6772 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6773 for (f = 0, foff = 0; f < numFields; ++f) { 6774 PetscInt fdof, cfdof; 6775 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6776 PetscInt cind = 0, b; 6777 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6778 6779 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6780 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6781 if (!cfdof || setBC) { 6782 for (b = 0; b < fdof; ++b) { 6783 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6784 const PetscInt ind = indperm ? indperm[preind] : preind; 6785 6786 indices[ind] = off+foff+b; 6787 } 6788 } else { 6789 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6790 for (b = 0; b < fdof; ++b) { 6791 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6792 const PetscInt ind = indperm ? indperm[preind] : preind; 6793 6794 if ((cind < cfdof) && (b == fcdofs[cind])) { 6795 indices[ind] = -(off+foff+b+1); 6796 ++cind; 6797 } else { 6798 indices[ind] = off + foff + b - (islocal ? 0 : cind); 6799 } 6800 } 6801 } 6802 foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6803 foffs[f] += fdof; 6804 } 6805 PetscFunctionReturn(0); 6806 } 6807 6808 /* 6809 This version believes the globalSection offsets for each field, rather than just the point offset 6810 6811 . foffs - The offset into 'indices' for each field, since it is segregated by field 6812 6813 Notes: 6814 The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6815 Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 6816 */ 6817 static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 6818 { 6819 PetscInt numFields, foff, f; 6820 PetscErrorCode ierr; 6821 6822 PetscFunctionBegin; 6823 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6824 for (f = 0; f < numFields; ++f) { 6825 PetscInt fdof, cfdof; 6826 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6827 PetscInt cind = 0, b; 6828 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6829 6830 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6831 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6832 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 6833 if (!cfdof) { 6834 for (b = 0; b < fdof; ++b) { 6835 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6836 const PetscInt ind = indperm ? indperm[preind] : preind; 6837 6838 indices[ind] = foff+b; 6839 } 6840 } else { 6841 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6842 for (b = 0; b < fdof; ++b) { 6843 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6844 const PetscInt ind = indperm ? indperm[preind] : preind; 6845 6846 if ((cind < cfdof) && (b == fcdofs[cind])) { 6847 indices[ind] = -(foff+b+1); 6848 ++cind; 6849 } else { 6850 indices[ind] = foff+b-cind; 6851 } 6852 } 6853 } 6854 foffs[f] += fdof; 6855 } 6856 PetscFunctionReturn(0); 6857 } 6858 6859 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) 6860 { 6861 Mat cMat; 6862 PetscSection aSec, cSec; 6863 IS aIS; 6864 PetscInt aStart = -1, aEnd = -1; 6865 const PetscInt *anchors; 6866 PetscInt numFields, f, p, q, newP = 0; 6867 PetscInt newNumPoints = 0, newNumIndices = 0; 6868 PetscInt *newPoints, *indices, *newIndices; 6869 PetscInt maxAnchor, maxDof; 6870 PetscInt newOffsets[32]; 6871 PetscInt *pointMatOffsets[32]; 6872 PetscInt *newPointOffsets[32]; 6873 PetscScalar *pointMat[32]; 6874 PetscScalar *newValues=NULL,*tmpValues; 6875 PetscBool anyConstrained = PETSC_FALSE; 6876 PetscErrorCode ierr; 6877 6878 PetscFunctionBegin; 6879 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6880 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6881 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6882 6883 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6884 /* if there are point-to-point constraints */ 6885 if (aSec) { 6886 ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr); 6887 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6888 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 6889 /* figure out how many points are going to be in the new element matrix 6890 * (we allow double counting, because it's all just going to be summed 6891 * into the global matrix anyway) */ 6892 for (p = 0; p < 2*numPoints; p+=2) { 6893 PetscInt b = points[p]; 6894 PetscInt bDof = 0, bSecDof; 6895 6896 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6897 if (!bSecDof) { 6898 continue; 6899 } 6900 if (b >= aStart && b < aEnd) { 6901 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 6902 } 6903 if (bDof) { 6904 /* this point is constrained */ 6905 /* it is going to be replaced by its anchors */ 6906 PetscInt bOff, q; 6907 6908 anyConstrained = PETSC_TRUE; 6909 newNumPoints += bDof; 6910 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 6911 for (q = 0; q < bDof; q++) { 6912 PetscInt a = anchors[bOff + q]; 6913 PetscInt aDof; 6914 6915 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6916 newNumIndices += aDof; 6917 for (f = 0; f < numFields; ++f) { 6918 PetscInt fDof; 6919 6920 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 6921 newOffsets[f+1] += fDof; 6922 } 6923 } 6924 } 6925 else { 6926 /* this point is not constrained */ 6927 newNumPoints++; 6928 newNumIndices += bSecDof; 6929 for (f = 0; f < numFields; ++f) { 6930 PetscInt fDof; 6931 6932 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6933 newOffsets[f+1] += fDof; 6934 } 6935 } 6936 } 6937 } 6938 if (!anyConstrained) { 6939 if (outNumPoints) *outNumPoints = 0; 6940 if (outNumIndices) *outNumIndices = 0; 6941 if (outPoints) *outPoints = NULL; 6942 if (outValues) *outValues = NULL; 6943 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6944 PetscFunctionReturn(0); 6945 } 6946 6947 if (outNumPoints) *outNumPoints = newNumPoints; 6948 if (outNumIndices) *outNumIndices = newNumIndices; 6949 6950 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6951 6952 if (!outPoints && !outValues) { 6953 if (offsets) { 6954 for (f = 0; f <= numFields; f++) { 6955 offsets[f] = newOffsets[f]; 6956 } 6957 } 6958 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6959 PetscFunctionReturn(0); 6960 } 6961 6962 PetscCheckFalse(numFields && newOffsets[numFields] != newNumIndices,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 6963 6964 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat, NULL);CHKERRQ(ierr); 6965 6966 /* workspaces */ 6967 if (numFields) { 6968 for (f = 0; f < numFields; f++) { 6969 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 6970 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6971 } 6972 } 6973 else { 6974 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 6975 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6976 } 6977 6978 /* get workspaces for the point-to-point matrices */ 6979 if (numFields) { 6980 PetscInt totalOffset, totalMatOffset; 6981 6982 for (p = 0; p < numPoints; p++) { 6983 PetscInt b = points[2*p]; 6984 PetscInt bDof = 0, bSecDof; 6985 6986 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6987 if (!bSecDof) { 6988 for (f = 0; f < numFields; f++) { 6989 newPointOffsets[f][p + 1] = 0; 6990 pointMatOffsets[f][p + 1] = 0; 6991 } 6992 continue; 6993 } 6994 if (b >= aStart && b < aEnd) { 6995 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6996 } 6997 if (bDof) { 6998 for (f = 0; f < numFields; f++) { 6999 PetscInt fDof, q, bOff, allFDof = 0; 7000 7001 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 7002 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 7003 for (q = 0; q < bDof; q++) { 7004 PetscInt a = anchors[bOff + q]; 7005 PetscInt aFDof; 7006 7007 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 7008 allFDof += aFDof; 7009 } 7010 newPointOffsets[f][p+1] = allFDof; 7011 pointMatOffsets[f][p+1] = fDof * allFDof; 7012 } 7013 } 7014 else { 7015 for (f = 0; f < numFields; f++) { 7016 PetscInt fDof; 7017 7018 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 7019 newPointOffsets[f][p+1] = fDof; 7020 pointMatOffsets[f][p+1] = 0; 7021 } 7022 } 7023 } 7024 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 7025 newPointOffsets[f][0] = totalOffset; 7026 pointMatOffsets[f][0] = totalMatOffset; 7027 for (p = 0; p < numPoints; p++) { 7028 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 7029 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 7030 } 7031 totalOffset = newPointOffsets[f][numPoints]; 7032 totalMatOffset = pointMatOffsets[f][numPoints]; 7033 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 7034 } 7035 } 7036 else { 7037 for (p = 0; p < numPoints; p++) { 7038 PetscInt b = points[2*p]; 7039 PetscInt bDof = 0, bSecDof; 7040 7041 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 7042 if (!bSecDof) { 7043 newPointOffsets[0][p + 1] = 0; 7044 pointMatOffsets[0][p + 1] = 0; 7045 continue; 7046 } 7047 if (b >= aStart && b < aEnd) { 7048 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 7049 } 7050 if (bDof) { 7051 PetscInt bOff, q, allDof = 0; 7052 7053 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 7054 for (q = 0; q < bDof; q++) { 7055 PetscInt a = anchors[bOff + q], aDof; 7056 7057 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 7058 allDof += aDof; 7059 } 7060 newPointOffsets[0][p+1] = allDof; 7061 pointMatOffsets[0][p+1] = bSecDof * allDof; 7062 } 7063 else { 7064 newPointOffsets[0][p+1] = bSecDof; 7065 pointMatOffsets[0][p+1] = 0; 7066 } 7067 } 7068 newPointOffsets[0][0] = 0; 7069 pointMatOffsets[0][0] = 0; 7070 for (p = 0; p < numPoints; p++) { 7071 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 7072 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 7073 } 7074 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 7075 } 7076 7077 /* output arrays */ 7078 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 7079 7080 /* get the point-to-point matrices; construct newPoints */ 7081 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 7082 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7083 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 7084 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 7085 if (numFields) { 7086 for (p = 0, newP = 0; p < numPoints; p++) { 7087 PetscInt b = points[2*p]; 7088 PetscInt o = points[2*p+1]; 7089 PetscInt bDof = 0, bSecDof; 7090 7091 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 7092 if (!bSecDof) { 7093 continue; 7094 } 7095 if (b >= aStart && b < aEnd) { 7096 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 7097 } 7098 if (bDof) { 7099 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 7100 7101 fStart[0] = 0; 7102 fEnd[0] = 0; 7103 for (f = 0; f < numFields; f++) { 7104 PetscInt fDof; 7105 7106 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 7107 fStart[f+1] = fStart[f] + fDof; 7108 fEnd[f+1] = fStart[f+1]; 7109 } 7110 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 7111 ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 7112 7113 fAnchorStart[0] = 0; 7114 fAnchorEnd[0] = 0; 7115 for (f = 0; f < numFields; f++) { 7116 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 7117 7118 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 7119 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 7120 } 7121 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 7122 for (q = 0; q < bDof; q++) { 7123 PetscInt a = anchors[bOff + q], aOff; 7124 7125 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 7126 newPoints[2*(newP + q)] = a; 7127 newPoints[2*(newP + q) + 1] = 0; 7128 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 7129 ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 7130 } 7131 newP += bDof; 7132 7133 if (outValues) { 7134 /* get the point-to-point submatrix */ 7135 for (f = 0; f < numFields; f++) { 7136 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 7137 } 7138 } 7139 } 7140 else { 7141 newPoints[2 * newP] = b; 7142 newPoints[2 * newP + 1] = o; 7143 newP++; 7144 } 7145 } 7146 } else { 7147 for (p = 0; p < numPoints; p++) { 7148 PetscInt b = points[2*p]; 7149 PetscInt o = points[2*p+1]; 7150 PetscInt bDof = 0, bSecDof; 7151 7152 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 7153 if (!bSecDof) { 7154 continue; 7155 } 7156 if (b >= aStart && b < aEnd) { 7157 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 7158 } 7159 if (bDof) { 7160 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7161 7162 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 7163 ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 7164 7165 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 7166 for (q = 0; q < bDof; q++) { 7167 PetscInt a = anchors[bOff + q], aOff; 7168 7169 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 7170 7171 newPoints[2*(newP + q)] = a; 7172 newPoints[2*(newP + q) + 1] = 0; 7173 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 7174 ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 7175 } 7176 newP += bDof; 7177 7178 /* get the point-to-point submatrix */ 7179 if (outValues) { 7180 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 7181 } 7182 } 7183 else { 7184 newPoints[2 * newP] = b; 7185 newPoints[2 * newP + 1] = o; 7186 newP++; 7187 } 7188 } 7189 } 7190 7191 if (outValues) { 7192 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7193 ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr); 7194 /* multiply constraints on the right */ 7195 if (numFields) { 7196 for (f = 0; f < numFields; f++) { 7197 PetscInt oldOff = offsets[f]; 7198 7199 for (p = 0; p < numPoints; p++) { 7200 PetscInt cStart = newPointOffsets[f][p]; 7201 PetscInt b = points[2 * p]; 7202 PetscInt c, r, k; 7203 PetscInt dof; 7204 7205 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7206 if (!dof) { 7207 continue; 7208 } 7209 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7210 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 7211 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7212 7213 for (r = 0; r < numIndices; r++) { 7214 for (c = 0; c < nCols; c++) { 7215 for (k = 0; k < dof; k++) { 7216 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7217 } 7218 } 7219 } 7220 } 7221 else { 7222 /* copy this column as is */ 7223 for (r = 0; r < numIndices; r++) { 7224 for (c = 0; c < dof; c++) { 7225 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7226 } 7227 } 7228 } 7229 oldOff += dof; 7230 } 7231 } 7232 } 7233 else { 7234 PetscInt oldOff = 0; 7235 for (p = 0; p < numPoints; p++) { 7236 PetscInt cStart = newPointOffsets[0][p]; 7237 PetscInt b = points[2 * p]; 7238 PetscInt c, r, k; 7239 PetscInt dof; 7240 7241 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7242 if (!dof) { 7243 continue; 7244 } 7245 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7246 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 7247 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7248 7249 for (r = 0; r < numIndices; r++) { 7250 for (c = 0; c < nCols; c++) { 7251 for (k = 0; k < dof; k++) { 7252 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7253 } 7254 } 7255 } 7256 } 7257 else { 7258 /* copy this column as is */ 7259 for (r = 0; r < numIndices; r++) { 7260 for (c = 0; c < dof; c++) { 7261 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7262 } 7263 } 7264 } 7265 oldOff += dof; 7266 } 7267 } 7268 7269 if (multiplyLeft) { 7270 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 7271 ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr); 7272 /* multiply constraints transpose on the left */ 7273 if (numFields) { 7274 for (f = 0; f < numFields; f++) { 7275 PetscInt oldOff = offsets[f]; 7276 7277 for (p = 0; p < numPoints; p++) { 7278 PetscInt rStart = newPointOffsets[f][p]; 7279 PetscInt b = points[2 * p]; 7280 PetscInt c, r, k; 7281 PetscInt dof; 7282 7283 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7284 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7285 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 7286 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7287 7288 for (r = 0; r < nRows; r++) { 7289 for (c = 0; c < newNumIndices; c++) { 7290 for (k = 0; k < dof; k++) { 7291 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7292 } 7293 } 7294 } 7295 } 7296 else { 7297 /* copy this row as is */ 7298 for (r = 0; r < dof; r++) { 7299 for (c = 0; c < newNumIndices; c++) { 7300 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7301 } 7302 } 7303 } 7304 oldOff += dof; 7305 } 7306 } 7307 } 7308 else { 7309 PetscInt oldOff = 0; 7310 7311 for (p = 0; p < numPoints; p++) { 7312 PetscInt rStart = newPointOffsets[0][p]; 7313 PetscInt b = points[2 * p]; 7314 PetscInt c, r, k; 7315 PetscInt dof; 7316 7317 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7318 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7319 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 7320 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7321 7322 for (r = 0; r < nRows; r++) { 7323 for (c = 0; c < newNumIndices; c++) { 7324 for (k = 0; k < dof; k++) { 7325 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7326 } 7327 } 7328 } 7329 } 7330 else { 7331 /* copy this row as is */ 7332 for (r = 0; r < dof; r++) { 7333 for (c = 0; c < newNumIndices; c++) { 7334 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7335 } 7336 } 7337 } 7338 oldOff += dof; 7339 } 7340 } 7341 7342 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7343 } 7344 else { 7345 newValues = tmpValues; 7346 } 7347 } 7348 7349 /* clean up */ 7350 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 7351 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 7352 7353 if (numFields) { 7354 for (f = 0; f < numFields; f++) { 7355 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 7356 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 7357 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 7358 } 7359 } 7360 else { 7361 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 7362 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 7363 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 7364 } 7365 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7366 7367 /* output */ 7368 if (outPoints) { 7369 *outPoints = newPoints; 7370 } 7371 else { 7372 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 7373 } 7374 if (outValues) { 7375 *outValues = newValues; 7376 } 7377 for (f = 0; f <= numFields; f++) { 7378 offsets[f] = newOffsets[f]; 7379 } 7380 PetscFunctionReturn(0); 7381 } 7382 7383 /*@C 7384 DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 7385 7386 Not collective 7387 7388 Input Parameters: 7389 + dm - The DM 7390 . section - The PetscSection describing the points (a local section) 7391 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7392 . point - The point defining the closure 7393 - useClPerm - Use the closure point permutation if available 7394 7395 Output Parameters: 7396 + numIndices - The number of dof indices in the closure of point with the input sections 7397 . indices - The dof indices 7398 . outOffsets - Array to write the field offsets into, or NULL 7399 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7400 7401 Notes: 7402 Must call DMPlexRestoreClosureIndices() to free allocated memory 7403 7404 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7405 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7406 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7407 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7408 indices (with the above semantics) are implied. 7409 7410 Level: advanced 7411 7412 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7413 @*/ 7414 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7415 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7416 { 7417 /* Closure ordering */ 7418 PetscSection clSection; 7419 IS clPoints; 7420 const PetscInt *clp; 7421 PetscInt *points; 7422 const PetscInt *clperm = NULL; 7423 /* Dof permutation and sign flips */ 7424 const PetscInt **perms[32] = {NULL}; 7425 const PetscScalar **flips[32] = {NULL}; 7426 PetscScalar *valCopy = NULL; 7427 /* Hanging node constraints */ 7428 PetscInt *pointsC = NULL; 7429 PetscScalar *valuesC = NULL; 7430 PetscInt NclC, NiC; 7431 7432 PetscInt *idx; 7433 PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 7434 PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 7435 PetscErrorCode ierr; 7436 7437 PetscFunctionBeginHot; 7438 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7439 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7440 PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7441 if (numIndices) PetscValidPointer(numIndices, 6); 7442 if (indices) PetscValidPointer(indices, 7); 7443 if (outOffsets) PetscValidPointer(outOffsets, 8); 7444 if (values) PetscValidPointer(values, 9); 7445 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 7446 PetscCheckFalse(Nf > 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 7447 ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 7448 /* 1) Get points in closure */ 7449 ierr = DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7450 if (useClPerm) { 7451 PetscInt depth, clsize; 7452 ierr = DMPlexGetPointDepth(dm, point, &depth);CHKERRQ(ierr); 7453 for (clsize=0,p=0; p<Ncl; p++) { 7454 PetscInt dof; 7455 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 7456 clsize += dof; 7457 } 7458 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 7459 } 7460 /* 2) Get number of indices on these points and field offsets from section */ 7461 for (p = 0; p < Ncl*2; p += 2) { 7462 PetscInt dof, fdof; 7463 7464 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7465 for (f = 0; f < Nf; ++f) { 7466 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7467 offsets[f+1] += fdof; 7468 } 7469 Ni += dof; 7470 } 7471 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 7472 PetscCheckFalse(Nf && offsets[Nf] != Ni,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni); 7473 /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 7474 for (f = 0; f < PetscMax(1, Nf); ++f) { 7475 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7476 else {ierr = PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7477 /* may need to apply sign changes to the element matrix */ 7478 if (values && flips[f]) { 7479 PetscInt foffset = offsets[f]; 7480 7481 for (p = 0; p < Ncl; ++p) { 7482 PetscInt pnt = points[2*p], fdof; 7483 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 7484 7485 if (!Nf) {ierr = PetscSectionGetDof(section, pnt, &fdof);CHKERRQ(ierr);} 7486 else {ierr = PetscSectionGetFieldDof(section, pnt, f, &fdof);CHKERRQ(ierr);} 7487 if (flip) { 7488 PetscInt i, j, k; 7489 7490 if (!valCopy) { 7491 ierr = DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr); 7492 for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 7493 *values = valCopy; 7494 } 7495 for (i = 0; i < fdof; ++i) { 7496 PetscScalar fval = flip[i]; 7497 7498 for (k = 0; k < Ni; ++k) { 7499 valCopy[Ni * (foffset + i) + k] *= fval; 7500 valCopy[Ni * k + (foffset + i)] *= fval; 7501 } 7502 } 7503 } 7504 foffset += fdof; 7505 } 7506 } 7507 } 7508 /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 7509 ierr = DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 7510 if (NclC) { 7511 if (valCopy) {ierr = DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);} 7512 for (f = 0; f < PetscMax(1, Nf); ++f) { 7513 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7514 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7515 } 7516 for (f = 0; f < PetscMax(1, Nf); ++f) { 7517 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7518 else {ierr = PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7519 } 7520 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7521 Ncl = NclC; 7522 Ni = NiC; 7523 points = pointsC; 7524 if (values) *values = valuesC; 7525 } 7526 /* 5) Calculate indices */ 7527 ierr = DMGetWorkArray(dm, Ni, MPIU_INT, &idx);CHKERRQ(ierr); 7528 if (Nf) { 7529 PetscInt idxOff; 7530 PetscBool useFieldOffsets; 7531 7532 if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 7533 ierr = PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets);CHKERRQ(ierr); 7534 if (useFieldOffsets) { 7535 for (p = 0; p < Ncl; ++p) { 7536 const PetscInt pnt = points[p*2]; 7537 7538 ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx);CHKERRQ(ierr); 7539 } 7540 } else { 7541 for (p = 0; p < Ncl; ++p) { 7542 const PetscInt pnt = points[p*2]; 7543 7544 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7545 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7546 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 7547 * global section. */ 7548 ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx);CHKERRQ(ierr); 7549 } 7550 } 7551 } else { 7552 PetscInt off = 0, idxOff; 7553 7554 for (p = 0; p < Ncl; ++p) { 7555 const PetscInt pnt = points[p*2]; 7556 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 7557 7558 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7559 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7560 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 7561 ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx);CHKERRQ(ierr); 7562 } 7563 } 7564 /* 6) Cleanup */ 7565 for (f = 0; f < PetscMax(1, Nf); ++f) { 7566 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7567 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7568 } 7569 if (NclC) { 7570 ierr = DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC);CHKERRQ(ierr); 7571 } else { 7572 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7573 } 7574 7575 if (numIndices) *numIndices = Ni; 7576 if (indices) *indices = idx; 7577 PetscFunctionReturn(0); 7578 } 7579 7580 /*@C 7581 DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 7582 7583 Not collective 7584 7585 Input Parameters: 7586 + dm - The DM 7587 . section - The PetscSection describing the points (a local section) 7588 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7589 . point - The point defining the closure 7590 - useClPerm - Use the closure point permutation if available 7591 7592 Output Parameters: 7593 + numIndices - The number of dof indices in the closure of point with the input sections 7594 . indices - The dof indices 7595 . outOffsets - Array to write the field offsets into, or NULL 7596 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7597 7598 Notes: 7599 If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 7600 7601 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7602 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7603 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7604 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7605 indices (with the above semantics) are implied. 7606 7607 Level: advanced 7608 7609 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7610 @*/ 7611 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7612 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7613 { 7614 PetscErrorCode ierr; 7615 7616 PetscFunctionBegin; 7617 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7618 PetscValidPointer(indices, 7); 7619 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 7620 PetscFunctionReturn(0); 7621 } 7622 7623 /*@C 7624 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 7625 7626 Not collective 7627 7628 Input Parameters: 7629 + dm - The DM 7630 . section - The section describing the layout in v, or NULL to use the default section 7631 . globalSection - The section describing the layout in v, or NULL to use the default global section 7632 . A - The matrix 7633 . point - The point in the DM 7634 . values - The array of values 7635 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7636 7637 Fortran Notes: 7638 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 7639 7640 Level: intermediate 7641 7642 .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7643 @*/ 7644 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7645 { 7646 DM_Plex *mesh = (DM_Plex*) dm->data; 7647 PetscInt *indices; 7648 PetscInt numIndices; 7649 const PetscScalar *valuesOrig = values; 7650 PetscErrorCode ierr; 7651 7652 PetscFunctionBegin; 7653 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7654 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 7655 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7656 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 7657 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 7658 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7659 7660 ierr = DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7661 7662 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 7663 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7664 if (ierr) { 7665 PetscMPIInt rank; 7666 PetscErrorCode ierr2; 7667 7668 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7669 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7670 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 7671 ierr2 = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7672 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7673 SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values"); 7674 } 7675 if (mesh->printFEM > 1) { 7676 PetscInt i; 7677 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 7678 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 7679 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7680 } 7681 7682 ierr = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7683 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7684 PetscFunctionReturn(0); 7685 } 7686 7687 /*@C 7688 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 7689 7690 Not collective 7691 7692 Input Parameters: 7693 + dmRow - The DM for the row fields 7694 . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 7695 . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 7696 . dmCol - The DM for the column fields 7697 . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 7698 . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 7699 . A - The matrix 7700 . point - The point in the DMs 7701 . values - The array of values 7702 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7703 7704 Level: intermediate 7705 7706 .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7707 @*/ 7708 PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7709 { 7710 DM_Plex *mesh = (DM_Plex*) dmRow->data; 7711 PetscInt *indicesRow, *indicesCol; 7712 PetscInt numIndicesRow, numIndicesCol; 7713 const PetscScalar *valuesOrig = values; 7714 PetscErrorCode ierr; 7715 7716 PetscFunctionBegin; 7717 PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 7718 if (!sectionRow) {ierr = DMGetLocalSection(dmRow, §ionRow);CHKERRQ(ierr);} 7719 PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 7720 if (!globalSectionRow) {ierr = DMGetGlobalSection(dmRow, &globalSectionRow);CHKERRQ(ierr);} 7721 PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 7722 PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 7723 if (!sectionCol) {ierr = DMGetLocalSection(dmCol, §ionCol);CHKERRQ(ierr);} 7724 PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 7725 if (!globalSectionCol) {ierr = DMGetGlobalSection(dmCol, &globalSectionCol);CHKERRQ(ierr);} 7726 PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 7727 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7728 7729 ierr = DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7730 ierr = DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7731 7732 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr);} 7733 ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 7734 if (ierr) { 7735 PetscMPIInt rank; 7736 PetscErrorCode ierr2; 7737 7738 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7739 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7740 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr2); 7741 ierr2 = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7742 ierr2 = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7743 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7744 CHKERRQ(ierr); 7745 } 7746 7747 ierr = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7748 ierr = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7749 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7750 PetscFunctionReturn(0); 7751 } 7752 7753 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7754 { 7755 DM_Plex *mesh = (DM_Plex*) dmf->data; 7756 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7757 PetscInt *cpoints = NULL; 7758 PetscInt *findices, *cindices; 7759 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7760 PetscInt foffsets[32], coffsets[32]; 7761 DMPolytopeType ct; 7762 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7763 PetscErrorCode ierr; 7764 7765 PetscFunctionBegin; 7766 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7767 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7768 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7769 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7770 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7771 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7772 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7773 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7774 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7775 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7776 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7777 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7778 PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7779 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7780 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7781 /* Column indices */ 7782 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7783 maxFPoints = numCPoints; 7784 /* Compress out points not in the section */ 7785 /* TODO: Squeeze out points with 0 dof as well */ 7786 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7787 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7788 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7789 cpoints[q*2] = cpoints[p]; 7790 cpoints[q*2+1] = cpoints[p+1]; 7791 ++q; 7792 } 7793 } 7794 numCPoints = q; 7795 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7796 PetscInt fdof; 7797 7798 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7799 if (!dof) continue; 7800 for (f = 0; f < numFields; ++f) { 7801 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7802 coffsets[f+1] += fdof; 7803 } 7804 numCIndices += dof; 7805 } 7806 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7807 /* Row indices */ 7808 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7809 { 7810 DMPlexTransform tr; 7811 DMPolytopeType *rct; 7812 PetscInt *rsize, *rcone, *rornt, Nt; 7813 7814 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7815 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7816 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7817 numSubcells = rsize[Nt-1]; 7818 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7819 } 7820 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7821 for (r = 0, q = 0; r < numSubcells; ++r) { 7822 /* TODO Map from coarse to fine cells */ 7823 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7824 /* Compress out points not in the section */ 7825 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7826 for (p = 0; p < numFPoints*2; p += 2) { 7827 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7828 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7829 if (!dof) continue; 7830 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7831 if (s < q) continue; 7832 ftotpoints[q*2] = fpoints[p]; 7833 ftotpoints[q*2+1] = fpoints[p+1]; 7834 ++q; 7835 } 7836 } 7837 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7838 } 7839 numFPoints = q; 7840 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7841 PetscInt fdof; 7842 7843 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7844 if (!dof) continue; 7845 for (f = 0; f < numFields; ++f) { 7846 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7847 foffsets[f+1] += fdof; 7848 } 7849 numFIndices += dof; 7850 } 7851 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7852 7853 PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7854 PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7855 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7856 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7857 if (numFields) { 7858 const PetscInt **permsF[32] = {NULL}; 7859 const PetscInt **permsC[32] = {NULL}; 7860 7861 for (f = 0; f < numFields; f++) { 7862 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7863 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7864 } 7865 for (p = 0; p < numFPoints; p++) { 7866 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7867 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7868 } 7869 for (p = 0; p < numCPoints; p++) { 7870 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7871 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7872 } 7873 for (f = 0; f < numFields; f++) { 7874 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7875 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7876 } 7877 } else { 7878 const PetscInt **permsF = NULL; 7879 const PetscInt **permsC = NULL; 7880 7881 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7882 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7883 for (p = 0, off = 0; p < numFPoints; p++) { 7884 const PetscInt *perm = permsF ? permsF[p] : NULL; 7885 7886 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7887 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7888 } 7889 for (p = 0, off = 0; p < numCPoints; p++) { 7890 const PetscInt *perm = permsC ? permsC[p] : NULL; 7891 7892 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7893 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7894 } 7895 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7896 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7897 } 7898 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 7899 /* TODO: flips */ 7900 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7901 if (ierr) { 7902 PetscMPIInt rank; 7903 PetscErrorCode ierr2; 7904 7905 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7906 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7907 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 7908 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 7909 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 7910 CHKERRQ(ierr); 7911 } 7912 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7913 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7914 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7915 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7916 PetscFunctionReturn(0); 7917 } 7918 7919 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 7920 { 7921 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7922 PetscInt *cpoints = NULL; 7923 PetscInt foffsets[32], coffsets[32]; 7924 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7925 DMPolytopeType ct; 7926 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7927 PetscErrorCode ierr; 7928 7929 PetscFunctionBegin; 7930 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7931 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7932 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7933 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7934 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7935 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7936 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7937 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7938 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7939 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7940 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7941 PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7942 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7943 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7944 /* Column indices */ 7945 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7946 maxFPoints = numCPoints; 7947 /* Compress out points not in the section */ 7948 /* TODO: Squeeze out points with 0 dof as well */ 7949 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7950 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7951 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7952 cpoints[q*2] = cpoints[p]; 7953 cpoints[q*2+1] = cpoints[p+1]; 7954 ++q; 7955 } 7956 } 7957 numCPoints = q; 7958 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7959 PetscInt fdof; 7960 7961 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7962 if (!dof) continue; 7963 for (f = 0; f < numFields; ++f) { 7964 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7965 coffsets[f+1] += fdof; 7966 } 7967 numCIndices += dof; 7968 } 7969 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7970 /* Row indices */ 7971 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7972 { 7973 DMPlexTransform tr; 7974 DMPolytopeType *rct; 7975 PetscInt *rsize, *rcone, *rornt, Nt; 7976 7977 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7978 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7979 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7980 numSubcells = rsize[Nt-1]; 7981 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7982 } 7983 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7984 for (r = 0, q = 0; r < numSubcells; ++r) { 7985 /* TODO Map from coarse to fine cells */ 7986 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7987 /* Compress out points not in the section */ 7988 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7989 for (p = 0; p < numFPoints*2; p += 2) { 7990 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7991 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7992 if (!dof) continue; 7993 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7994 if (s < q) continue; 7995 ftotpoints[q*2] = fpoints[p]; 7996 ftotpoints[q*2+1] = fpoints[p+1]; 7997 ++q; 7998 } 7999 } 8000 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 8001 } 8002 numFPoints = q; 8003 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 8004 PetscInt fdof; 8005 8006 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 8007 if (!dof) continue; 8008 for (f = 0; f < numFields; ++f) { 8009 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 8010 foffsets[f+1] += fdof; 8011 } 8012 numFIndices += dof; 8013 } 8014 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 8015 8016 PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 8017 PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 8018 if (numFields) { 8019 const PetscInt **permsF[32] = {NULL}; 8020 const PetscInt **permsC[32] = {NULL}; 8021 8022 for (f = 0; f < numFields; f++) { 8023 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 8024 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 8025 } 8026 for (p = 0; p < numFPoints; p++) { 8027 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 8028 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 8029 } 8030 for (p = 0; p < numCPoints; p++) { 8031 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 8032 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 8033 } 8034 for (f = 0; f < numFields; f++) { 8035 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 8036 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 8037 } 8038 } else { 8039 const PetscInt **permsF = NULL; 8040 const PetscInt **permsC = NULL; 8041 8042 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 8043 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 8044 for (p = 0, off = 0; p < numFPoints; p++) { 8045 const PetscInt *perm = permsF ? permsF[p] : NULL; 8046 8047 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 8048 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 8049 } 8050 for (p = 0, off = 0; p < numCPoints; p++) { 8051 const PetscInt *perm = permsC ? permsC[p] : NULL; 8052 8053 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 8054 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 8055 } 8056 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 8057 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 8058 } 8059 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 8060 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 8061 PetscFunctionReturn(0); 8062 } 8063 8064 /*@C 8065 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 8066 8067 Input Parameter: 8068 . dm - The DMPlex object 8069 8070 Output Parameter: 8071 . cellHeight - The height of a cell 8072 8073 Level: developer 8074 8075 .seealso DMPlexSetVTKCellHeight() 8076 @*/ 8077 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8078 { 8079 DM_Plex *mesh = (DM_Plex*) dm->data; 8080 8081 PetscFunctionBegin; 8082 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8083 PetscValidPointer(cellHeight, 2); 8084 *cellHeight = mesh->vtkCellHeight; 8085 PetscFunctionReturn(0); 8086 } 8087 8088 /*@C 8089 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 8090 8091 Input Parameters: 8092 + dm - The DMPlex object 8093 - cellHeight - The height of a cell 8094 8095 Level: developer 8096 8097 .seealso DMPlexGetVTKCellHeight() 8098 @*/ 8099 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8100 { 8101 DM_Plex *mesh = (DM_Plex*) dm->data; 8102 8103 PetscFunctionBegin; 8104 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8105 mesh->vtkCellHeight = cellHeight; 8106 PetscFunctionReturn(0); 8107 } 8108 8109 /*@ 8110 DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 8111 8112 Input Parameter: 8113 . dm - The DMPlex object 8114 8115 Output Parameters: 8116 + gcStart - The first ghost cell, or NULL 8117 - gcEnd - The upper bound on ghost cells, or NULL 8118 8119 Level: advanced 8120 8121 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 8122 @*/ 8123 PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 8124 { 8125 DMLabel ctLabel; 8126 PetscErrorCode ierr; 8127 8128 PetscFunctionBegin; 8129 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8130 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 8131 ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr); 8132 PetscFunctionReturn(0); 8133 } 8134 8135 PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8136 { 8137 PetscSection section, globalSection; 8138 PetscInt *numbers, p; 8139 PetscErrorCode ierr; 8140 8141 PetscFunctionBegin; 8142 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 8143 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 8144 for (p = pStart; p < pEnd; ++p) { 8145 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 8146 } 8147 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 8148 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8149 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 8150 for (p = pStart; p < pEnd; ++p) { 8151 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 8152 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 8153 else numbers[p-pStart] += shift; 8154 } 8155 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 8156 if (globalSize) { 8157 PetscLayout layout; 8158 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 8159 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 8160 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 8161 } 8162 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 8163 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8164 PetscFunctionReturn(0); 8165 } 8166 8167 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8168 { 8169 PetscInt cellHeight, cStart, cEnd; 8170 PetscErrorCode ierr; 8171 8172 PetscFunctionBegin; 8173 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8174 if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 8175 else {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 8176 ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 8177 PetscFunctionReturn(0); 8178 } 8179 8180 /*@ 8181 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 8182 8183 Input Parameter: 8184 . dm - The DMPlex object 8185 8186 Output Parameter: 8187 . globalCellNumbers - Global cell numbers for all cells on this process 8188 8189 Level: developer 8190 8191 .seealso DMPlexGetVertexNumbering() 8192 @*/ 8193 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8194 { 8195 DM_Plex *mesh = (DM_Plex*) dm->data; 8196 PetscErrorCode ierr; 8197 8198 PetscFunctionBegin; 8199 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8200 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 8201 *globalCellNumbers = mesh->globalCellNumbers; 8202 PetscFunctionReturn(0); 8203 } 8204 8205 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8206 { 8207 PetscInt vStart, vEnd; 8208 PetscErrorCode ierr; 8209 8210 PetscFunctionBegin; 8211 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8212 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8213 ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 8214 PetscFunctionReturn(0); 8215 } 8216 8217 /*@ 8218 DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 8219 8220 Input Parameter: 8221 . dm - The DMPlex object 8222 8223 Output Parameter: 8224 . globalVertexNumbers - Global vertex numbers for all vertices on this process 8225 8226 Level: developer 8227 8228 .seealso DMPlexGetCellNumbering() 8229 @*/ 8230 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8231 { 8232 DM_Plex *mesh = (DM_Plex*) dm->data; 8233 PetscErrorCode ierr; 8234 8235 PetscFunctionBegin; 8236 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8237 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 8238 *globalVertexNumbers = mesh->globalVertexNumbers; 8239 PetscFunctionReturn(0); 8240 } 8241 8242 /*@ 8243 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 8244 8245 Input Parameter: 8246 . dm - The DMPlex object 8247 8248 Output Parameter: 8249 . globalPointNumbers - Global numbers for all points on this process 8250 8251 Level: developer 8252 8253 .seealso DMPlexGetCellNumbering() 8254 @*/ 8255 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8256 { 8257 IS nums[4]; 8258 PetscInt depths[4], gdepths[4], starts[4]; 8259 PetscInt depth, d, shift = 0; 8260 PetscErrorCode ierr; 8261 8262 PetscFunctionBegin; 8263 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8264 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8265 /* For unstratified meshes use dim instead of depth */ 8266 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 8267 for (d = 0; d <= depth; ++d) { 8268 PetscInt end; 8269 8270 depths[d] = depth-d; 8271 ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 8272 if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 8273 } 8274 ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 8275 ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 8276 for (d = 0; d <= depth; ++d) { 8277 PetscCheckFalse(starts[d] >= 0 && depths[d] != gdepths[d],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 8278 } 8279 for (d = 0; d <= depth; ++d) { 8280 PetscInt pStart, pEnd, gsize; 8281 8282 ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 8283 ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 8284 shift += gsize; 8285 } 8286 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 8287 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 8288 PetscFunctionReturn(0); 8289 } 8290 8291 /*@ 8292 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 8293 8294 Input Parameter: 8295 . dm - The DMPlex object 8296 8297 Output Parameter: 8298 . ranks - The rank field 8299 8300 Options Database Keys: 8301 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 8302 8303 Level: intermediate 8304 8305 .seealso: DMView() 8306 @*/ 8307 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8308 { 8309 DM rdm; 8310 PetscFE fe; 8311 PetscScalar *r; 8312 PetscMPIInt rank; 8313 DMPolytopeType ct; 8314 PetscInt dim, cStart, cEnd, c; 8315 PetscBool simplex; 8316 PetscErrorCode ierr; 8317 8318 PetscFunctionBeginUser; 8319 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8320 PetscValidPointer(ranks, 2); 8321 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 8322 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8323 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8324 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8325 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 8326 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 8327 ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 8328 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 8329 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8330 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8331 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8332 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 8333 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 8334 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 8335 for (c = cStart; c < cEnd; ++c) { 8336 PetscScalar *lr; 8337 8338 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 8339 if (lr) *lr = rank; 8340 } 8341 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 8342 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8343 PetscFunctionReturn(0); 8344 } 8345 8346 /*@ 8347 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 8348 8349 Input Parameters: 8350 + dm - The DMPlex 8351 - label - The DMLabel 8352 8353 Output Parameter: 8354 . val - The label value field 8355 8356 Options Database Keys: 8357 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 8358 8359 Level: intermediate 8360 8361 .seealso: DMView() 8362 @*/ 8363 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8364 { 8365 DM rdm; 8366 PetscFE fe; 8367 PetscScalar *v; 8368 PetscInt dim, cStart, cEnd, c; 8369 PetscErrorCode ierr; 8370 8371 PetscFunctionBeginUser; 8372 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8373 PetscValidPointer(label, 2); 8374 PetscValidPointer(val, 3); 8375 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8376 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8377 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 8378 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 8379 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8380 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8381 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8382 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8383 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 8384 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 8385 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 8386 for (c = cStart; c < cEnd; ++c) { 8387 PetscScalar *lv; 8388 PetscInt cval; 8389 8390 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 8391 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 8392 *lv = cval; 8393 } 8394 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 8395 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8396 PetscFunctionReturn(0); 8397 } 8398 8399 /*@ 8400 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8401 8402 Input Parameter: 8403 . dm - The DMPlex object 8404 8405 Notes: 8406 This is a useful diagnostic when creating meshes programmatically. 8407 8408 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8409 8410 Level: developer 8411 8412 .seealso: DMCreate(), DMSetFromOptions() 8413 @*/ 8414 PetscErrorCode DMPlexCheckSymmetry(DM dm) 8415 { 8416 PetscSection coneSection, supportSection; 8417 const PetscInt *cone, *support; 8418 PetscInt coneSize, c, supportSize, s; 8419 PetscInt pStart, pEnd, p, pp, csize, ssize; 8420 PetscBool storagecheck = PETSC_TRUE; 8421 PetscErrorCode ierr; 8422 8423 PetscFunctionBegin; 8424 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8425 ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr); 8426 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 8427 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 8428 /* Check that point p is found in the support of its cone points, and vice versa */ 8429 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8430 for (p = pStart; p < pEnd; ++p) { 8431 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8432 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8433 for (c = 0; c < coneSize; ++c) { 8434 PetscBool dup = PETSC_FALSE; 8435 PetscInt d; 8436 for (d = c-1; d >= 0; --d) { 8437 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 8438 } 8439 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 8440 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 8441 for (s = 0; s < supportSize; ++s) { 8442 if (support[s] == p) break; 8443 } 8444 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 8445 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 8446 for (s = 0; s < coneSize; ++s) { 8447 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 8448 } 8449 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8450 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 8451 for (s = 0; s < supportSize; ++s) { 8452 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 8453 } 8454 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8455 PetscCheckFalse(dup,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 8456 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 8457 } 8458 } 8459 ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 8460 if (p != pp) { storagecheck = PETSC_FALSE; continue; } 8461 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 8462 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 8463 for (s = 0; s < supportSize; ++s) { 8464 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 8465 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 8466 for (c = 0; c < coneSize; ++c) { 8467 ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 8468 if (cone[c] != pp) { c = 0; break; } 8469 if (cone[c] == p) break; 8470 } 8471 if (c >= coneSize) { 8472 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 8473 for (c = 0; c < supportSize; ++c) { 8474 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 8475 } 8476 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8477 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 8478 for (c = 0; c < coneSize; ++c) { 8479 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 8480 } 8481 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8482 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 8483 } 8484 } 8485 } 8486 if (storagecheck) { 8487 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 8488 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 8489 PetscCheckFalse(csize != ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 8490 } 8491 PetscFunctionReturn(0); 8492 } 8493 8494 /* 8495 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. 8496 */ 8497 static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8498 { 8499 DMPolytopeType cct; 8500 PetscInt ptpoints[4]; 8501 const PetscInt *cone, *ccone, *ptcone; 8502 PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8503 PetscErrorCode ierr; 8504 8505 PetscFunctionBegin; 8506 *unsplit = 0; 8507 switch (ct) { 8508 case DM_POLYTOPE_POINT_PRISM_TENSOR: 8509 ptpoints[npt++] = c; 8510 break; 8511 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8512 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8513 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8514 for (cp = 0; cp < coneSize; ++cp) { 8515 ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr); 8516 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8517 } 8518 break; 8519 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8520 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8521 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8522 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8523 for (cp = 0; cp < coneSize; ++cp) { 8524 ierr = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr); 8525 ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr); 8526 for (ccp = 0; ccp < cconeSize; ++ccp) { 8527 ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr); 8528 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8529 PetscInt p; 8530 for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8531 if (p == npt) ptpoints[npt++] = ccone[ccp]; 8532 } 8533 } 8534 } 8535 break; 8536 default: break; 8537 } 8538 for (pt = 0; pt < npt; ++pt) { 8539 ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr); 8540 if (ptcone[0] == ptcone[1]) ++(*unsplit); 8541 } 8542 PetscFunctionReturn(0); 8543 } 8544 8545 /*@ 8546 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8547 8548 Input Parameters: 8549 + dm - The DMPlex object 8550 - cellHeight - Normally 0 8551 8552 Notes: 8553 This is a useful diagnostic when creating meshes programmatically. 8554 Currently applicable only to homogeneous simplex or tensor meshes. 8555 8556 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8557 8558 Level: developer 8559 8560 .seealso: DMCreate(), DMSetFromOptions() 8561 @*/ 8562 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8563 { 8564 DMPlexInterpolatedFlag interp; 8565 DMPolytopeType ct; 8566 PetscInt vStart, vEnd, cStart, cEnd, c; 8567 PetscErrorCode ierr; 8568 8569 PetscFunctionBegin; 8570 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8571 ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr); 8572 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8573 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8574 for (c = cStart; c < cEnd; ++c) { 8575 PetscInt *closure = NULL; 8576 PetscInt coneSize, closureSize, cl, Nv = 0; 8577 8578 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8579 PetscCheckFalse((PetscInt) ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c); 8580 if (ct == DM_POLYTOPE_UNKNOWN) continue; 8581 if (interp == DMPLEX_INTERPOLATED_FULL) { 8582 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8583 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)); 8584 } 8585 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8586 for (cl = 0; cl < closureSize*2; cl += 2) { 8587 const PetscInt p = closure[cl]; 8588 if ((p >= vStart) && (p < vEnd)) ++Nv; 8589 } 8590 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8591 /* Special Case: Tensor faces with identified vertices */ 8592 if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8593 PetscInt unsplit; 8594 8595 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8596 if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 8597 } 8598 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)); 8599 } 8600 PetscFunctionReturn(0); 8601 } 8602 8603 /*@ 8604 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 8605 8606 Not Collective 8607 8608 Input Parameters: 8609 + dm - The DMPlex object 8610 - cellHeight - Normally 0 8611 8612 Notes: 8613 This is a useful diagnostic when creating meshes programmatically. 8614 This routine is only relevant for meshes that are fully interpolated across all ranks. 8615 It will error out if a partially interpolated mesh is given on some rank. 8616 It will do nothing for locally uninterpolated mesh (as there is nothing to check). 8617 8618 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8619 8620 Level: developer 8621 8622 .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 8623 @*/ 8624 PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 8625 { 8626 PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8627 PetscErrorCode ierr; 8628 DMPlexInterpolatedFlag interpEnum; 8629 8630 PetscFunctionBegin; 8631 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8632 ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr); 8633 if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 8634 if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 8635 PetscMPIInt rank; 8636 MPI_Comm comm; 8637 8638 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8639 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8640 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 8641 } 8642 8643 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8644 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8645 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8646 for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 8647 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 8648 for (c = cStart; c < cEnd; ++c) { 8649 const PetscInt *cone, *ornt, *faceSizes, *faces; 8650 const DMPolytopeType *faceTypes; 8651 DMPolytopeType ct; 8652 PetscInt numFaces, coneSize, f; 8653 PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 8654 8655 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8656 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8657 if (unsplit) continue; 8658 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8659 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8660 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 8661 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8662 for (cl = 0; cl < closureSize*2; cl += 2) { 8663 const PetscInt p = closure[cl]; 8664 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 8665 } 8666 ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8667 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); 8668 for (f = 0; f < numFaces; ++f) { 8669 DMPolytopeType fct; 8670 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 8671 8672 ierr = DMPlexGetCellType(dm, cone[f], &fct);CHKERRQ(ierr); 8673 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8674 for (cl = 0; cl < fclosureSize*2; cl += 2) { 8675 const PetscInt p = fclosure[cl]; 8676 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 8677 } 8678 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]); 8679 for (v = 0; v < fnumCorners; ++v) { 8680 if (fclosure[v] != faces[fOff+v]) { 8681 PetscInt v1; 8682 8683 ierr = PetscPrintf(PETSC_COMM_SELF, "face closure:");CHKERRQ(ierr); 8684 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", fclosure[v1]);CHKERRQ(ierr);} 8685 ierr = PetscPrintf(PETSC_COMM_SELF, "\ncell face:");CHKERRQ(ierr); 8686 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", faces[fOff+v1]);CHKERRQ(ierr);} 8687 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8688 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]); 8689 } 8690 } 8691 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8692 fOff += faceSizes[f]; 8693 } 8694 ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8695 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8696 } 8697 } 8698 PetscFunctionReturn(0); 8699 } 8700 8701 /*@ 8702 DMPlexCheckGeometry - Check the geometry of mesh cells 8703 8704 Input Parameter: 8705 . dm - The DMPlex object 8706 8707 Notes: 8708 This is a useful diagnostic when creating meshes programmatically. 8709 8710 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8711 8712 Level: developer 8713 8714 .seealso: DMCreate(), DMSetFromOptions() 8715 @*/ 8716 PetscErrorCode DMPlexCheckGeometry(DM dm) 8717 { 8718 Vec coordinates; 8719 PetscReal detJ, J[9], refVol = 1.0; 8720 PetscReal vol; 8721 PetscBool periodic; 8722 PetscInt dim, depth, dE, d, cStart, cEnd, c; 8723 PetscErrorCode ierr; 8724 8725 PetscFunctionBegin; 8726 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8727 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 8728 if (dim != dE) PetscFunctionReturn(0); 8729 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8730 ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr); 8731 for (d = 0; d < dim; ++d) refVol *= 2.0; 8732 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8733 /* Make sure local coordinates are created, because that step is collective */ 8734 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8735 for (c = cStart; c < cEnd; ++c) { 8736 DMPolytopeType ct; 8737 PetscInt unsplit; 8738 PetscBool ignoreZeroVol = PETSC_FALSE; 8739 8740 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8741 switch (ct) { 8742 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8743 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8744 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8745 ignoreZeroVol = PETSC_TRUE; break; 8746 default: break; 8747 } 8748 switch (ct) { 8749 case DM_POLYTOPE_TRI_PRISM: 8750 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8751 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8752 case DM_POLYTOPE_PYRAMID: 8753 continue; 8754 default: break; 8755 } 8756 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8757 if (unsplit) continue; 8758 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 8759 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); 8760 ierr = PetscInfo(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 8761 if (depth > 1 && !periodic) { 8762 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 8763 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); 8764 ierr = PetscInfo(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 8765 } 8766 } 8767 PetscFunctionReturn(0); 8768 } 8769 8770 /*@ 8771 DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 8772 8773 Input Parameters: 8774 . dm - The DMPlex object 8775 8776 Notes: 8777 This is mainly intended for debugging/testing purposes. 8778 It currently checks only meshes with no partition overlapping. 8779 8780 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8781 8782 Level: developer 8783 8784 .seealso: DMGetPointSF(), DMSetFromOptions() 8785 @*/ 8786 PetscErrorCode DMPlexCheckPointSF(DM dm) 8787 { 8788 PetscSF pointSF; 8789 PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 8790 const PetscInt *locals, *rootdegree; 8791 PetscBool distributed; 8792 PetscErrorCode ierr; 8793 8794 PetscFunctionBegin; 8795 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8796 ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr); 8797 ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 8798 if (!distributed) PetscFunctionReturn(0); 8799 ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 8800 if (overlap) { 8801 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping");CHKERRQ(ierr); 8802 PetscFunctionReturn(0); 8803 } 8804 PetscCheckFalse(!pointSF,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 8805 ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr); 8806 PetscCheckFalse(nroots < 0,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 8807 ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 8808 ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 8809 8810 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 8811 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8812 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8813 for (l = 0; l < nleaves; ++l) { 8814 const PetscInt point = locals[l]; 8815 8816 PetscCheckFalse(point >= cStart && point < cEnd,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 8817 } 8818 8819 /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 8820 for (l = 0; l < nleaves; ++l) { 8821 const PetscInt point = locals[l]; 8822 const PetscInt *cone; 8823 PetscInt coneSize, c, idx; 8824 8825 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 8826 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 8827 for (c = 0; c < coneSize; ++c) { 8828 if (!rootdegree[cone[c]]) { 8829 ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr); 8830 PetscCheckFalse(idx < 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 8831 } 8832 } 8833 } 8834 PetscFunctionReturn(0); 8835 } 8836 8837 PetscErrorCode DMPlexCheckAll_Internal(DM dm, PetscInt cellHeight) 8838 { 8839 PetscErrorCode ierr; 8840 8841 PetscFunctionBegin; 8842 ierr = DMPlexCheckSymmetry(dm);CHKERRQ(ierr); 8843 ierr = DMPlexCheckSkeleton(dm, cellHeight);CHKERRQ(ierr); 8844 ierr = DMPlexCheckFaces(dm, cellHeight);CHKERRQ(ierr); 8845 ierr = DMPlexCheckGeometry(dm);CHKERRQ(ierr); 8846 ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr); 8847 ierr = DMPlexCheckInterfaceCones(dm);CHKERRQ(ierr); 8848 PetscFunctionReturn(0); 8849 } 8850 8851 typedef struct cell_stats 8852 { 8853 PetscReal min, max, sum, squaresum; 8854 PetscInt count; 8855 } cell_stats_t; 8856 8857 static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8858 { 8859 PetscInt i, N = *len; 8860 8861 for (i = 0; i < N; i++) { 8862 cell_stats_t *A = (cell_stats_t *) a; 8863 cell_stats_t *B = (cell_stats_t *) b; 8864 8865 B->min = PetscMin(A->min,B->min); 8866 B->max = PetscMax(A->max,B->max); 8867 B->sum += A->sum; 8868 B->squaresum += A->squaresum; 8869 B->count += A->count; 8870 } 8871 } 8872 8873 /*@ 8874 DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8875 8876 Collective on dm 8877 8878 Input Parameters: 8879 + dm - The DMPlex object 8880 . output - If true, statistics will be displayed on stdout 8881 - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8882 8883 Notes: 8884 This is mainly intended for debugging/testing purposes. 8885 8886 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8887 8888 Level: developer 8889 8890 .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality() 8891 @*/ 8892 PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8893 { 8894 DM dmCoarse; 8895 cell_stats_t stats, globalStats; 8896 MPI_Comm comm = PetscObjectComm((PetscObject)dm); 8897 PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 8898 PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8899 PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 8900 PetscMPIInt rank,size; 8901 PetscErrorCode ierr; 8902 8903 PetscFunctionBegin; 8904 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8905 stats.min = PETSC_MAX_REAL; 8906 stats.max = PETSC_MIN_REAL; 8907 stats.sum = stats.squaresum = 0.; 8908 stats.count = 0; 8909 8910 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 8911 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8912 ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr); 8913 ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr); 8914 ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 8915 ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); 8916 for (c = cStart; c < cEnd; c++) { 8917 PetscInt i; 8918 PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8919 8920 ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 8921 PetscCheckFalse(detJ < 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 8922 for (i = 0; i < PetscSqr(cdim); ++i) { 8923 frobJ += J[i] * J[i]; 8924 frobInvJ += invJ[i] * invJ[i]; 8925 } 8926 cond2 = frobJ * frobInvJ; 8927 cond = PetscSqrtReal(cond2); 8928 8929 stats.min = PetscMin(stats.min,cond); 8930 stats.max = PetscMax(stats.max,cond); 8931 stats.sum += cond; 8932 stats.squaresum += cond2; 8933 stats.count++; 8934 if (output && cond > limit) { 8935 PetscSection coordSection; 8936 Vec coordsLocal; 8937 PetscScalar *coords = NULL; 8938 PetscInt Nv, d, clSize, cl, *closure = NULL; 8939 8940 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8941 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8942 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8943 ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr); 8944 for (i = 0; i < Nv/cdim; ++i) { 8945 ierr = PetscSynchronizedPrintf(comm, " Vertex %D: (", i);CHKERRQ(ierr); 8946 for (d = 0; d < cdim; ++d) { 8947 if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);} 8948 ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr); 8949 } 8950 ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr); 8951 } 8952 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8953 for (cl = 0; cl < clSize*2; cl += 2) { 8954 const PetscInt edge = closure[cl]; 8955 8956 if ((edge >= eStart) && (edge < eEnd)) { 8957 PetscReal len; 8958 8959 ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr); 8960 ierr = PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr); 8961 } 8962 } 8963 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8964 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8965 } 8966 } 8967 if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 8968 8969 if (size > 1) { 8970 PetscMPIInt blockLengths[2] = {4,1}; 8971 MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8972 MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8973 MPI_Op statReduce; 8974 8975 ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRMPI(ierr); 8976 ierr = MPI_Type_commit(&statType);CHKERRMPI(ierr); 8977 ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRMPI(ierr); 8978 ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRMPI(ierr); 8979 ierr = MPI_Op_free(&statReduce);CHKERRMPI(ierr); 8980 ierr = MPI_Type_free(&statType);CHKERRMPI(ierr); 8981 } else { 8982 ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr); 8983 } 8984 if (rank == 0) { 8985 count = globalStats.count; 8986 min = globalStats.min; 8987 max = globalStats.max; 8988 mean = globalStats.sum / globalStats.count; 8989 stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8990 } 8991 8992 if (output) { 8993 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); 8994 } 8995 ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 8996 8997 ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 8998 if (dmCoarse) { 8999 PetscBool isplex; 9000 9001 ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 9002 if (isplex) { 9003 ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr); 9004 } 9005 } 9006 PetscFunctionReturn(0); 9007 } 9008 9009 /*@ 9010 DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 9011 orthogonal quality below given tolerance. 9012 9013 Collective on dm 9014 9015 Input Parameters: 9016 + dm - The DMPlex object 9017 . fv - Optional PetscFV object for pre-computed cell/face centroid information 9018 - atol - [0, 1] Absolute tolerance for tagging cells. 9019 9020 Output Parameters: 9021 + OrthQual - Vec containing orthogonal quality per cell 9022 - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 9023 9024 Options Database Keys: 9025 + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 9026 supported. 9027 - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 9028 9029 Notes: 9030 Orthogonal quality is given by the following formula: 9031 9032 \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 9033 9034 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 9035 is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 9036 current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 9037 calculating the cosine of the angle between these vectors. 9038 9039 Orthogonal quality ranges from 1 (best) to 0 (worst). 9040 9041 This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 9042 pre-computed FVM cell data, but if it is not passed in then this data will be computed. 9043 9044 Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 9045 9046 Level: intermediate 9047 9048 .seealso: DMPlexCheckCellShape(), DMCreateLabel() 9049 @*/ 9050 PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 9051 { 9052 PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 9053 PetscInt *idx; 9054 PetscScalar *oqVals; 9055 const PetscScalar *cellGeomArr, *faceGeomArr; 9056 PetscReal *ci, *fi, *Ai; 9057 MPI_Comm comm; 9058 Vec cellgeom, facegeom; 9059 DM dmFace, dmCell; 9060 IS glob; 9061 ISLocalToGlobalMapping ltog; 9062 PetscViewer vwr; 9063 PetscErrorCode ierr; 9064 9065 PetscFunctionBegin; 9066 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9067 if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 9068 PetscValidPointer(OrthQual, 4); 9069 PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol); 9070 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 9071 ierr = DMGetDimension(dm, &nc);CHKERRQ(ierr); 9072 PetscCheckFalse(nc < 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc); 9073 { 9074 DMPlexInterpolatedFlag interpFlag; 9075 9076 ierr = DMPlexIsInterpolated(dm, &interpFlag);CHKERRQ(ierr); 9077 if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 9078 PetscMPIInt rank; 9079 9080 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 9081 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 9082 } 9083 } 9084 if (OrthQualLabel) { 9085 PetscValidPointer(OrthQualLabel, 5); 9086 ierr = DMCreateLabel(dm, "Orthogonal_Quality");CHKERRQ(ierr); 9087 ierr = DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel);CHKERRQ(ierr); 9088 } else {*OrthQualLabel = NULL;} 9089 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9090 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9091 ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob);CHKERRQ(ierr); 9092 ierr = ISLocalToGlobalMappingCreateIS(glob, <og);CHKERRQ(ierr); 9093 ierr = ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 9094 ierr = VecCreate(comm, OrthQual);CHKERRQ(ierr); 9095 ierr = VecSetType(*OrthQual, VECSTANDARD);CHKERRQ(ierr); 9096 ierr = VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr); 9097 ierr = VecSetLocalToGlobalMapping(*OrthQual, ltog);CHKERRQ(ierr); 9098 ierr = VecSetUp(*OrthQual);CHKERRQ(ierr); 9099 ierr = ISDestroy(&glob);CHKERRQ(ierr); 9100 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 9101 ierr = DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL);CHKERRQ(ierr); 9102 ierr = VecGetArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 9103 ierr = VecGetArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 9104 ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr); 9105 ierr = VecGetDM(facegeom, &dmFace);CHKERRQ(ierr); 9106 ierr = PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai);CHKERRQ(ierr); 9107 for (cell = cStart; cell < cEnd; cellIter++,cell++) { 9108 PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9109 PetscInt cellarr[2], *adj = NULL; 9110 PetscScalar *cArr, *fArr; 9111 PetscReal minvalc = 1.0, minvalf = 1.0; 9112 PetscFVCellGeom *cg; 9113 9114 idx[cellIter] = cell-cStart; 9115 cellarr[0] = cell; 9116 /* Make indexing into cellGeom easier */ 9117 ierr = DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg);CHKERRQ(ierr); 9118 ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj);CHKERRQ(ierr); 9119 /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 9120 ierr = PetscCalloc2(adjSize, &cArr, adjSize, &fArr);CHKERRQ(ierr); 9121 for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 9122 PetscInt i; 9123 const PetscInt neigh = adj[cellneigh]; 9124 PetscReal normci = 0, normfi = 0, normai = 0; 9125 PetscFVCellGeom *cgneigh; 9126 PetscFVFaceGeom *fg; 9127 9128 /* Don't count ourselves in the neighbor list */ 9129 if (neigh == cell) continue; 9130 ierr = DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh);CHKERRQ(ierr); 9131 cellarr[1] = neigh; 9132 { 9133 PetscInt numcovpts; 9134 const PetscInt *covpts; 9135 9136 ierr = DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 9137 ierr = DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg);CHKERRQ(ierr); 9138 ierr = DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 9139 } 9140 9141 /* Compute c_i, f_i and their norms */ 9142 for (i = 0; i < nc; i++) { 9143 ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9144 fi[i] = fg->centroid[i] - cg->centroid[i]; 9145 Ai[i] = fg->normal[i]; 9146 normci += PetscPowReal(ci[i], 2); 9147 normfi += PetscPowReal(fi[i], 2); 9148 normai += PetscPowReal(Ai[i], 2); 9149 } 9150 normci = PetscSqrtReal(normci); 9151 normfi = PetscSqrtReal(normfi); 9152 normai = PetscSqrtReal(normai); 9153 9154 /* Normalize and compute for each face-cell-normal pair */ 9155 for (i = 0; i < nc; i++) { 9156 ci[i] = ci[i]/normci; 9157 fi[i] = fi[i]/normfi; 9158 Ai[i] = Ai[i]/normai; 9159 /* PetscAbs because I don't know if normals are guaranteed to point out */ 9160 cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 9161 fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 9162 } 9163 if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 9164 minvalc = PetscRealPart(cArr[cellneighiter]); 9165 } 9166 if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 9167 minvalf = PetscRealPart(fArr[cellneighiter]); 9168 } 9169 } 9170 ierr = PetscFree(adj);CHKERRQ(ierr); 9171 ierr = PetscFree2(cArr, fArr);CHKERRQ(ierr); 9172 /* Defer to cell if they're equal */ 9173 oqVals[cellIter] = PetscMin(minvalf, minvalc); 9174 if (OrthQualLabel) { 9175 if (PetscRealPart(oqVals[cellIter]) <= atol) {ierr = DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE);CHKERRQ(ierr);} 9176 } 9177 } 9178 ierr = VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES);CHKERRQ(ierr); 9179 ierr = VecAssemblyBegin(*OrthQual);CHKERRQ(ierr); 9180 ierr = VecAssemblyEnd(*OrthQual);CHKERRQ(ierr); 9181 ierr = VecRestoreArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 9182 ierr = VecRestoreArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 9183 ierr = PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL);CHKERRQ(ierr); 9184 if (OrthQualLabel) { 9185 if (vwr) {ierr = DMLabelView(*OrthQualLabel, vwr);CHKERRQ(ierr);} 9186 } 9187 ierr = PetscFree5(idx, oqVals, ci, fi, Ai);CHKERRQ(ierr); 9188 ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr); 9189 ierr = VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view");CHKERRQ(ierr); 9190 PetscFunctionReturn(0); 9191 } 9192 9193 /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 9194 * interpolator construction */ 9195 static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9196 { 9197 PetscSection section, newSection, gsection; 9198 PetscSF sf; 9199 PetscBool hasConstraints, ghasConstraints; 9200 PetscErrorCode ierr; 9201 9202 PetscFunctionBegin; 9203 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9204 PetscValidPointer(odm,2); 9205 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9206 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 9207 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 9208 if (!ghasConstraints) { 9209 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 9210 *odm = dm; 9211 PetscFunctionReturn(0); 9212 } 9213 ierr = DMClone(dm, odm);CHKERRQ(ierr); 9214 ierr = DMCopyFields(dm, *odm);CHKERRQ(ierr); 9215 ierr = DMGetLocalSection(*odm, &newSection);CHKERRQ(ierr); 9216 ierr = DMGetPointSF(*odm, &sf);CHKERRQ(ierr); 9217 ierr = PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 9218 ierr = DMSetGlobalSection(*odm, gsection);CHKERRQ(ierr); 9219 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 9220 PetscFunctionReturn(0); 9221 } 9222 9223 static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9224 { 9225 DM dmco, dmfo; 9226 Mat interpo; 9227 Vec rscale; 9228 Vec cglobalo, clocal; 9229 Vec fglobal, fglobalo, flocal; 9230 PetscBool regular; 9231 PetscErrorCode ierr; 9232 9233 PetscFunctionBegin; 9234 ierr = DMGetFullDM(dmc, &dmco);CHKERRQ(ierr); 9235 ierr = DMGetFullDM(dmf, &dmfo);CHKERRQ(ierr); 9236 ierr = DMSetCoarseDM(dmfo, dmco);CHKERRQ(ierr); 9237 ierr = DMPlexGetRegularRefinement(dmf, ®ular);CHKERRQ(ierr); 9238 ierr = DMPlexSetRegularRefinement(dmfo, regular);CHKERRQ(ierr); 9239 ierr = DMCreateInterpolation(dmco, dmfo, &interpo, &rscale);CHKERRQ(ierr); 9240 ierr = DMCreateGlobalVector(dmco, &cglobalo);CHKERRQ(ierr); 9241 ierr = DMCreateLocalVector(dmc, &clocal);CHKERRQ(ierr); 9242 ierr = VecSet(cglobalo, 0.);CHKERRQ(ierr); 9243 ierr = VecSet(clocal, 0.);CHKERRQ(ierr); 9244 ierr = DMCreateGlobalVector(dmf, &fglobal);CHKERRQ(ierr); 9245 ierr = DMCreateGlobalVector(dmfo, &fglobalo);CHKERRQ(ierr); 9246 ierr = DMCreateLocalVector(dmf, &flocal);CHKERRQ(ierr); 9247 ierr = VecSet(fglobal, 0.);CHKERRQ(ierr); 9248 ierr = VecSet(fglobalo, 0.);CHKERRQ(ierr); 9249 ierr = VecSet(flocal, 0.);CHKERRQ(ierr); 9250 ierr = DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL);CHKERRQ(ierr); 9251 ierr = DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9252 ierr = DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9253 ierr = MatMult(interpo, cglobalo, fglobalo);CHKERRQ(ierr); 9254 ierr = DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9255 ierr = DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9256 ierr = DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9257 ierr = DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9258 *shift = fglobal; 9259 ierr = VecDestroy(&flocal);CHKERRQ(ierr); 9260 ierr = VecDestroy(&fglobalo);CHKERRQ(ierr); 9261 ierr = VecDestroy(&clocal);CHKERRQ(ierr); 9262 ierr = VecDestroy(&cglobalo);CHKERRQ(ierr); 9263 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9264 ierr = MatDestroy(&interpo);CHKERRQ(ierr); 9265 ierr = DMDestroy(&dmfo);CHKERRQ(ierr); 9266 ierr = DMDestroy(&dmco);CHKERRQ(ierr); 9267 PetscFunctionReturn(0); 9268 } 9269 9270 PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9271 { 9272 PetscObject shifto; 9273 Vec shift; 9274 9275 PetscErrorCode ierr; 9276 9277 PetscFunctionBegin; 9278 if (!interp) { 9279 Vec rscale; 9280 9281 ierr = DMCreateInterpolation(coarse, fine, &interp, &rscale);CHKERRQ(ierr); 9282 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9283 } else { 9284 ierr = PetscObjectReference((PetscObject)interp);CHKERRQ(ierr); 9285 } 9286 ierr = PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto);CHKERRQ(ierr); 9287 if (!shifto) { 9288 ierr = DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift);CHKERRQ(ierr); 9289 ierr = PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift);CHKERRQ(ierr); 9290 shifto = (PetscObject) shift; 9291 ierr = VecDestroy(&shift);CHKERRQ(ierr); 9292 } 9293 shift = (Vec) shifto; 9294 ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr); 9295 ierr = VecAXPY(fineSol, 1.0, shift);CHKERRQ(ierr); 9296 ierr = MatDestroy(&interp);CHKERRQ(ierr); 9297 PetscFunctionReturn(0); 9298 } 9299 9300 /* Pointwise interpolation 9301 Just code FEM for now 9302 u^f = I u^c 9303 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 9304 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 9305 I_{ij} = psi^f_i phi^c_j 9306 */ 9307 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9308 { 9309 PetscSection gsc, gsf; 9310 PetscInt m, n; 9311 void *ctx; 9312 DM cdm; 9313 PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9314 PetscErrorCode ierr; 9315 9316 PetscFunctionBegin; 9317 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9318 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9319 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9320 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9321 9322 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 9323 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 9324 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9325 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 9326 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9327 9328 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9329 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9330 if (!isRefined || (regular && cdm == dmCoarse)) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx);CHKERRQ(ierr);} 9331 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 9332 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 9333 if (scaling) { 9334 /* Use naive scaling */ 9335 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 9336 } 9337 PetscFunctionReturn(0); 9338 } 9339 9340 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9341 { 9342 PetscErrorCode ierr; 9343 VecScatter ctx; 9344 9345 PetscFunctionBegin; 9346 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 9347 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 9348 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 9349 PetscFunctionReturn(0); 9350 } 9351 9352 static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9353 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9354 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9355 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 9356 { 9357 const PetscInt Nc = uOff[1] - uOff[0]; 9358 PetscInt c; 9359 for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0; 9360 } 9361 9362 PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9363 { 9364 DM dmc; 9365 PetscDS ds; 9366 Vec ones, locmass; 9367 IS cellIS; 9368 PetscFormKey key; 9369 PetscInt depth; 9370 PetscErrorCode ierr; 9371 9372 PetscFunctionBegin; 9373 ierr = DMClone(dm, &dmc);CHKERRQ(ierr); 9374 ierr = DMCopyDisc(dm, dmc);CHKERRQ(ierr); 9375 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9376 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9377 ierr = DMCreateGlobalVector(dmc, mass);CHKERRQ(ierr); 9378 ierr = DMGetLocalVector(dmc, &ones);CHKERRQ(ierr); 9379 ierr = DMGetLocalVector(dmc, &locmass);CHKERRQ(ierr); 9380 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9381 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9382 ierr = VecSet(locmass, 0.0);CHKERRQ(ierr); 9383 ierr = VecSet(ones, 1.0);CHKERRQ(ierr); 9384 key.label = NULL; 9385 key.value = 0; 9386 key.field = 0; 9387 key.part = 0; 9388 ierr = DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL);CHKERRQ(ierr); 9389 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9390 ierr = VecSet(*mass, 0.0);CHKERRQ(ierr); 9391 ierr = DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass);CHKERRQ(ierr); 9392 ierr = DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass);CHKERRQ(ierr); 9393 ierr = DMRestoreLocalVector(dmc, &ones);CHKERRQ(ierr); 9394 ierr = DMRestoreLocalVector(dmc, &locmass);CHKERRQ(ierr); 9395 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9396 PetscFunctionReturn(0); 9397 } 9398 9399 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9400 { 9401 PetscSection gsc, gsf; 9402 PetscInt m, n; 9403 void *ctx; 9404 DM cdm; 9405 PetscBool regular; 9406 PetscErrorCode ierr; 9407 9408 PetscFunctionBegin; 9409 if (dmFine == dmCoarse) { 9410 DM dmc; 9411 PetscDS ds; 9412 PetscWeakForm wf; 9413 Vec u; 9414 IS cellIS; 9415 PetscFormKey key; 9416 PetscInt depth; 9417 9418 ierr = DMClone(dmFine, &dmc);CHKERRQ(ierr); 9419 ierr = DMCopyDisc(dmFine, dmc);CHKERRQ(ierr); 9420 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9421 ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr); 9422 ierr = PetscWeakFormClear(wf);CHKERRQ(ierr); 9423 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9424 ierr = DMCreateMatrix(dmc, mass);CHKERRQ(ierr); 9425 ierr = DMGetGlobalVector(dmc, &u);CHKERRQ(ierr); 9426 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9427 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9428 ierr = MatZeroEntries(*mass);CHKERRQ(ierr); 9429 key.label = NULL; 9430 key.value = 0; 9431 key.field = 0; 9432 key.part = 0; 9433 ierr = DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL);CHKERRQ(ierr); 9434 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9435 ierr = DMRestoreGlobalVector(dmc, &u);CHKERRQ(ierr); 9436 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9437 } else { 9438 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9439 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9440 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9441 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9442 9443 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 9444 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9445 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 9446 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9447 9448 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9449 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9450 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9451 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9452 } 9453 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 9454 PetscFunctionReturn(0); 9455 } 9456 9457 /*@ 9458 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9459 9460 Input Parameter: 9461 . dm - The DMPlex object 9462 9463 Output Parameter: 9464 . regular - The flag 9465 9466 Level: intermediate 9467 9468 .seealso: DMPlexSetRegularRefinement() 9469 @*/ 9470 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 9471 { 9472 PetscFunctionBegin; 9473 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9474 PetscValidPointer(regular, 2); 9475 *regular = ((DM_Plex *) dm->data)->regularRefinement; 9476 PetscFunctionReturn(0); 9477 } 9478 9479 /*@ 9480 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9481 9482 Input Parameters: 9483 + dm - The DMPlex object 9484 - regular - The flag 9485 9486 Level: intermediate 9487 9488 .seealso: DMPlexGetRegularRefinement() 9489 @*/ 9490 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 9491 { 9492 PetscFunctionBegin; 9493 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9494 ((DM_Plex *) dm->data)->regularRefinement = regular; 9495 PetscFunctionReturn(0); 9496 } 9497 9498 /* anchors */ 9499 /*@ 9500 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9501 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints(). 9502 9503 not collective 9504 9505 Input Parameter: 9506 . dm - The DMPlex object 9507 9508 Output Parameters: 9509 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9510 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9511 9512 Level: intermediate 9513 9514 .seealso: DMPlexSetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints() 9515 @*/ 9516 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9517 { 9518 DM_Plex *plex = (DM_Plex *)dm->data; 9519 PetscErrorCode ierr; 9520 9521 PetscFunctionBegin; 9522 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9523 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 9524 if (anchorSection) *anchorSection = plex->anchorSection; 9525 if (anchorIS) *anchorIS = plex->anchorIS; 9526 PetscFunctionReturn(0); 9527 } 9528 9529 /*@ 9530 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9531 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9532 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9533 9534 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9535 DMGetDefaultConstraints() and filling in the entries in the constraint matrix. 9536 9537 collective on dm 9538 9539 Input Parameters: 9540 + dm - The DMPlex object 9541 . 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). 9542 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9543 9544 The reference counts of anchorSection and anchorIS are incremented. 9545 9546 Level: intermediate 9547 9548 .seealso: DMPlexGetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints() 9549 @*/ 9550 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9551 { 9552 DM_Plex *plex = (DM_Plex *)dm->data; 9553 PetscMPIInt result; 9554 PetscErrorCode ierr; 9555 9556 PetscFunctionBegin; 9557 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9558 if (anchorSection) { 9559 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 9560 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRMPI(ierr); 9561 PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9562 } 9563 if (anchorIS) { 9564 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 9565 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRMPI(ierr); 9566 PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9567 } 9568 9569 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 9570 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 9571 plex->anchorSection = anchorSection; 9572 9573 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 9574 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 9575 plex->anchorIS = anchorIS; 9576 9577 if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9578 PetscInt size, a, pStart, pEnd; 9579 const PetscInt *anchors; 9580 9581 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9582 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 9583 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 9584 for (a = 0; a < size; a++) { 9585 PetscInt p; 9586 9587 p = anchors[a]; 9588 if (p >= pStart && p < pEnd) { 9589 PetscInt dof; 9590 9591 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9592 if (dof) { 9593 PetscErrorCode ierr2; 9594 9595 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 9596 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 9597 } 9598 } 9599 } 9600 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 9601 } 9602 /* reset the generic constraints */ 9603 ierr = DMSetDefaultConstraints(dm,NULL,NULL,NULL);CHKERRQ(ierr); 9604 PetscFunctionReturn(0); 9605 } 9606 9607 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9608 { 9609 PetscSection anchorSection; 9610 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9611 PetscErrorCode ierr; 9612 9613 PetscFunctionBegin; 9614 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9615 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9616 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 9617 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9618 if (numFields) { 9619 PetscInt f; 9620 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 9621 9622 for (f = 0; f < numFields; f++) { 9623 PetscInt numComp; 9624 9625 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 9626 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 9627 } 9628 } 9629 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9630 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9631 pStart = PetscMax(pStart,sStart); 9632 pEnd = PetscMin(pEnd,sEnd); 9633 pEnd = PetscMax(pStart,pEnd); 9634 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 9635 for (p = pStart; p < pEnd; p++) { 9636 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9637 if (dof) { 9638 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 9639 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 9640 for (f = 0; f < numFields; f++) { 9641 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 9642 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 9643 } 9644 } 9645 } 9646 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 9647 ierr = PetscObjectSetName((PetscObject) *cSec, "Constraint Section");CHKERRQ(ierr); 9648 PetscFunctionReturn(0); 9649 } 9650 9651 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9652 { 9653 PetscSection aSec; 9654 PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 9655 const PetscInt *anchors; 9656 PetscInt numFields, f; 9657 IS aIS; 9658 PetscErrorCode ierr; 9659 MatType mtype; 9660 PetscBool iscuda,iskokkos; 9661 9662 PetscFunctionBegin; 9663 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9664 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 9665 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 9666 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 9667 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 9668 ierr = PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr); 9669 if (!iscuda) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr); } 9670 ierr = PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos);CHKERRQ(ierr); 9671 if (!iskokkos) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos);CHKERRQ(ierr); } 9672 if (iscuda) mtype = MATSEQAIJCUSPARSE; 9673 else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9674 else mtype = MATSEQAIJ; 9675 ierr = MatSetType(*cMat,mtype);CHKERRQ(ierr); 9676 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 9677 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 9678 /* cSec will be a subset of aSec and section */ 9679 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 9680 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9681 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 9682 i[0] = 0; 9683 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9684 for (p = pStart; p < pEnd; p++) { 9685 PetscInt rDof, rOff, r; 9686 9687 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9688 if (!rDof) continue; 9689 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9690 if (numFields) { 9691 for (f = 0; f < numFields; f++) { 9692 annz = 0; 9693 for (r = 0; r < rDof; r++) { 9694 a = anchors[rOff + r]; 9695 if (a < sStart || a >= sEnd) continue; 9696 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9697 annz += aDof; 9698 } 9699 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9700 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 9701 for (q = 0; q < dof; q++) { 9702 i[off + q + 1] = i[off + q] + annz; 9703 } 9704 } 9705 } else { 9706 annz = 0; 9707 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9708 for (q = 0; q < dof; q++) { 9709 a = anchors[rOff + q]; 9710 if (a < sStart || a >= sEnd) continue; 9711 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9712 annz += aDof; 9713 } 9714 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9715 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 9716 for (q = 0; q < dof; q++) { 9717 i[off + q + 1] = i[off + q] + annz; 9718 } 9719 } 9720 } 9721 nnz = i[m]; 9722 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 9723 offset = 0; 9724 for (p = pStart; p < pEnd; p++) { 9725 if (numFields) { 9726 for (f = 0; f < numFields; f++) { 9727 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9728 for (q = 0; q < dof; q++) { 9729 PetscInt rDof, rOff, r; 9730 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9731 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9732 for (r = 0; r < rDof; r++) { 9733 PetscInt s; 9734 9735 a = anchors[rOff + r]; 9736 if (a < sStart || a >= sEnd) continue; 9737 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9738 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 9739 for (s = 0; s < aDof; s++) { 9740 j[offset++] = aOff + s; 9741 } 9742 } 9743 } 9744 } 9745 } else { 9746 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9747 for (q = 0; q < dof; q++) { 9748 PetscInt rDof, rOff, r; 9749 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9750 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9751 for (r = 0; r < rDof; r++) { 9752 PetscInt s; 9753 9754 a = anchors[rOff + r]; 9755 if (a < sStart || a >= sEnd) continue; 9756 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9757 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 9758 for (s = 0; s < aDof; s++) { 9759 j[offset++] = aOff + s; 9760 } 9761 } 9762 } 9763 } 9764 } 9765 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 9766 ierr = PetscFree(i);CHKERRQ(ierr); 9767 ierr = PetscFree(j);CHKERRQ(ierr); 9768 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 9769 PetscFunctionReturn(0); 9770 } 9771 9772 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 9773 { 9774 DM_Plex *plex = (DM_Plex *)dm->data; 9775 PetscSection anchorSection, section, cSec; 9776 Mat cMat; 9777 PetscErrorCode ierr; 9778 9779 PetscFunctionBegin; 9780 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9781 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9782 if (anchorSection) { 9783 PetscInt Nf; 9784 9785 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 9786 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 9787 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 9788 ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 9789 if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 9790 ierr = DMSetDefaultConstraints(dm,cSec,cMat,NULL);CHKERRQ(ierr); 9791 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 9792 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 9793 } 9794 PetscFunctionReturn(0); 9795 } 9796 9797 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9798 { 9799 IS subis; 9800 PetscSection section, subsection; 9801 PetscErrorCode ierr; 9802 9803 PetscFunctionBegin; 9804 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9805 PetscCheckFalse(!section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 9806 PetscCheckFalse(!subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9807 /* Create subdomain */ 9808 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 9809 /* Create submodel */ 9810 ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr); 9811 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 9812 ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr); 9813 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 9814 ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 9815 /* Create map from submodel to global model */ 9816 if (is) { 9817 PetscSection sectionGlobal, subsectionGlobal; 9818 IS spIS; 9819 const PetscInt *spmap; 9820 PetscInt *subIndices; 9821 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9822 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9823 9824 ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 9825 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 9826 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 9827 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 9828 ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 9829 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 9830 for (p = pStart; p < pEnd; ++p) { 9831 PetscInt gdof, pSubSize = 0; 9832 9833 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 9834 if (gdof > 0) { 9835 for (f = 0; f < Nf; ++f) { 9836 PetscInt fdof, fcdof; 9837 9838 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 9839 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 9840 pSubSize += fdof-fcdof; 9841 } 9842 subSize += pSubSize; 9843 if (pSubSize) { 9844 if (bs < 0) { 9845 bs = pSubSize; 9846 } else if (bs != pSubSize) { 9847 /* Layout does not admit a pointwise block size */ 9848 bs = 1; 9849 } 9850 } 9851 } 9852 } 9853 /* Must have same blocksize on all procs (some might have no points) */ 9854 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 9855 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 9856 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9857 else {bs = bsMinMax[0];} 9858 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 9859 for (p = pStart; p < pEnd; ++p) { 9860 PetscInt gdof, goff; 9861 9862 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 9863 if (gdof > 0) { 9864 const PetscInt point = spmap[p]; 9865 9866 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 9867 for (f = 0; f < Nf; ++f) { 9868 PetscInt fdof, fcdof, fc, f2, poff = 0; 9869 9870 /* Can get rid of this loop by storing field information in the global section */ 9871 for (f2 = 0; f2 < f; ++f2) { 9872 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 9873 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 9874 poff += fdof-fcdof; 9875 } 9876 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 9877 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 9878 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9879 subIndices[subOff] = goff+poff+fc; 9880 } 9881 } 9882 } 9883 } 9884 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 9885 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 9886 if (bs > 1) { 9887 /* We need to check that the block size does not come from non-contiguous fields */ 9888 PetscInt i, j, set = 1; 9889 for (i = 0; i < subSize; i += bs) { 9890 for (j = 0; j < bs; ++j) { 9891 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9892 } 9893 } 9894 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 9895 } 9896 /* Attach nullspace */ 9897 for (f = 0; f < Nf; ++f) { 9898 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9899 if ((*subdm)->nullspaceConstructors[f]) break; 9900 } 9901 if (f < Nf) { 9902 MatNullSpace nullSpace; 9903 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace);CHKERRQ(ierr); 9904 9905 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 9906 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 9907 } 9908 } 9909 PetscFunctionReturn(0); 9910 } 9911 9912 /*@ 9913 DMPlexMonitorThroughput - Report the cell throughput of FE integration 9914 9915 Input Parameter: 9916 - dm - The DM 9917 9918 Level: developer 9919 9920 Options Database Keys: 9921 . -dm_plex_monitor_throughput - Activate the monitor 9922 9923 .seealso: DMSetFromOptions(), DMPlexCreate() 9924 @*/ 9925 PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9926 { 9927 #if defined(PETSC_USE_LOG) 9928 PetscStageLog stageLog; 9929 PetscLogEvent event; 9930 PetscLogStage stage; 9931 PetscEventPerfInfo eventInfo; 9932 PetscReal cellRate, flopRate; 9933 PetscInt cStart, cEnd, Nf, N; 9934 const char *name; 9935 PetscErrorCode ierr; 9936 #endif 9937 9938 PetscFunctionBegin; 9939 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9940 #if defined(PETSC_USE_LOG) 9941 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 9942 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9943 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9944 ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 9945 ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr); 9946 ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr); 9947 ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr); 9948 N = (cEnd - cStart)*Nf*eventInfo.count; 9949 flopRate = eventInfo.flops/eventInfo.time; 9950 cellRate = N/eventInfo.time; 9951 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); 9952 #else 9953 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9954 #endif 9955 PetscFunctionReturn(0); 9956 } 9957