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 10 /* Logging support */ 11 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; 12 13 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 14 15 /*@ 16 DMPlexIsSimplex - Is the first cell in this mesh a simplex? 17 18 Input Parameter: 19 . dm - The DMPlex object 20 21 Output Parameter: 22 . simplex - Flag checking for a simplex 23 24 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 25 If the mesh has no cells, this returns PETSC_FALSE. 26 27 Level: intermediate 28 29 .seealso DMPlexGetSimplexOrBoxCells(), DMPlexGetCellType(), DMPlexGetHeightStratum(), DMPolytopeTypeGetNumVertices() 30 @*/ 31 PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 32 { 33 DMPolytopeType ct; 34 PetscInt cStart, cEnd; 35 PetscErrorCode ierr; 36 37 PetscFunctionBegin; 38 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 39 if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);} 40 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 41 *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 42 PetscFunctionReturn(0); 43 } 44 45 /*@ 46 DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 47 48 Input Parameter: 49 + dm - The DMPlex object 50 - height - The cell height in the Plex, 0 is the default 51 52 Output Parameters: 53 + cStart - The first "normal" cell 54 - cEnd - The upper bound on "normal"" cells 55 56 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 57 58 Level: developer 59 60 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 61 @*/ 62 PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 63 { 64 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 65 PetscInt cS, cE, c; 66 PetscErrorCode ierr; 67 68 PetscFunctionBegin; 69 ierr = DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE);CHKERRQ(ierr); 70 for (c = cS; c < cE; ++c) { 71 DMPolytopeType cct; 72 73 ierr = DMPlexGetCellType(dm, c, &cct);CHKERRQ(ierr); 74 if ((PetscInt) cct < 0) break; 75 switch (cct) { 76 case DM_POLYTOPE_POINT: 77 case DM_POLYTOPE_SEGMENT: 78 case DM_POLYTOPE_TRIANGLE: 79 case DM_POLYTOPE_QUADRILATERAL: 80 case DM_POLYTOPE_TETRAHEDRON: 81 case DM_POLYTOPE_HEXAHEDRON: 82 ct = cct; 83 break; 84 default: break; 85 } 86 if (ct != DM_POLYTOPE_UNKNOWN) break; 87 } 88 if (ct != DM_POLYTOPE_UNKNOWN) { 89 DMLabel ctLabel; 90 91 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 92 ierr = DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE);CHKERRQ(ierr); 93 } 94 if (cStart) *cStart = cS; 95 if (cEnd) *cEnd = cE; 96 PetscFunctionReturn(0); 97 } 98 99 PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 100 { 101 PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 102 PetscInt vcdof[2] = {0,0}, globalvcdof[2]; 103 PetscErrorCode ierr; 104 105 PetscFunctionBegin; 106 *ft = PETSC_VTK_INVALID; 107 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 108 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 109 ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 110 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 111 if (field >= 0) { 112 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]);CHKERRQ(ierr);} 113 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]);CHKERRQ(ierr);} 114 } else { 115 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vcdof[0]);CHKERRQ(ierr);} 116 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &vcdof[1]);CHKERRQ(ierr);} 117 } 118 ierr = MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 119 if (globalvcdof[0]) { 120 *sStart = vStart; 121 *sEnd = vEnd; 122 if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 123 else *ft = PETSC_VTK_POINT_FIELD; 124 } else if (globalvcdof[1]) { 125 *sStart = cStart; 126 *sEnd = cEnd; 127 if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 128 else *ft = PETSC_VTK_CELL_FIELD; 129 } else { 130 if (field >= 0) { 131 const char *fieldname; 132 133 ierr = PetscSectionGetFieldName(section, field, &fieldname);CHKERRQ(ierr); 134 ierr = PetscInfo2((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname);CHKERRQ(ierr); 135 } else { 136 ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\"%s\"\n");CHKERRQ(ierr); 137 } 138 } 139 PetscFunctionReturn(0); 140 } 141 142 static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 143 { 144 DM dm; 145 PetscSection s; 146 PetscDraw draw, popup; 147 DM cdm; 148 PetscSection coordSection; 149 Vec coordinates; 150 const PetscScalar *coords, *array; 151 PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 152 PetscReal vbound[2], time; 153 PetscBool isnull, flg; 154 PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 155 const char *name; 156 char title[PETSC_MAX_PATH_LEN]; 157 PetscErrorCode ierr; 158 159 PetscFunctionBegin; 160 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 161 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 162 if (isnull) PetscFunctionReturn(0); 163 164 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 165 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 166 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D. Use PETSCVIEWERGLVIS", dim); 167 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 168 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 169 ierr = DMGetCoarsenLevel(dm, &level);CHKERRQ(ierr); 170 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 171 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 172 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 173 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 174 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 175 176 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 177 ierr = DMGetOutputSequenceNumber(dm, &step, &time);CHKERRQ(ierr); 178 179 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 180 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 181 for (c = 0; c < N; c += dim) { 182 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 183 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 184 } 185 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 186 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 187 188 /* Could implement something like DMDASelectFields() */ 189 for (f = 0; f < Nf; ++f) { 190 DM fdm = dm; 191 Vec fv = v; 192 IS fis; 193 char prefix[PETSC_MAX_PATH_LEN]; 194 const char *fname; 195 196 ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr); 197 ierr = PetscSectionGetFieldName(s, f, &fname);CHKERRQ(ierr); 198 199 if (v->hdr.prefix) {ierr = PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix));CHKERRQ(ierr);} 200 else {prefix[0] = '\0';} 201 if (Nf > 1) { 202 ierr = DMCreateSubDM(dm, 1, &f, &fis, &fdm);CHKERRQ(ierr); 203 ierr = VecGetSubVector(v, fis, &fv);CHKERRQ(ierr); 204 ierr = PetscStrlcat(prefix, fname,sizeof(prefix));CHKERRQ(ierr); 205 ierr = PetscStrlcat(prefix, "_",sizeof(prefix));CHKERRQ(ierr); 206 } 207 for (comp = 0; comp < Nc; ++comp, ++w) { 208 PetscInt nmax = 2; 209 210 ierr = PetscViewerDrawGetDraw(viewer, w, &draw);CHKERRQ(ierr); 211 if (Nc > 1) {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time);CHKERRQ(ierr);} 212 else {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time);CHKERRQ(ierr);} 213 ierr = PetscDrawSetTitle(draw, title);CHKERRQ(ierr); 214 215 /* TODO Get max and min only for this component */ 216 ierr = PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg);CHKERRQ(ierr); 217 if (!flg) { 218 ierr = VecMin(fv, NULL, &vbound[0]);CHKERRQ(ierr); 219 ierr = VecMax(fv, NULL, &vbound[1]);CHKERRQ(ierr); 220 if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 221 } 222 ierr = PetscDrawGetPopup(draw, &popup);CHKERRQ(ierr); 223 ierr = PetscDrawScalePopup(popup, vbound[0], vbound[1]);CHKERRQ(ierr); 224 ierr = PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]);CHKERRQ(ierr); 225 226 ierr = VecGetArrayRead(fv, &array);CHKERRQ(ierr); 227 for (c = cStart; c < cEnd; ++c) { 228 PetscScalar *coords = NULL, *a = NULL; 229 PetscInt numCoords, color[4] = {-1,-1,-1,-1}; 230 231 ierr = DMPlexPointLocalRead(fdm, c, array, &a);CHKERRQ(ierr); 232 if (a) { 233 color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 234 color[1] = color[2] = color[3] = color[0]; 235 } else { 236 PetscScalar *vals = NULL; 237 PetscInt numVals, va; 238 239 ierr = DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 240 if (numVals % Nc) SETERRQ2(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); 241 switch (numVals/Nc) { 242 case 3: /* P1 Triangle */ 243 case 4: /* P1 Quadrangle */ 244 for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]); 245 break; 246 case 6: /* P2 Triangle */ 247 case 8: /* P2 Quadrangle */ 248 for (va = 0; va < numVals/(Nc*2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp + numVals/(Nc*2)]), vbound[0], vbound[1]); 249 break; 250 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc); 251 } 252 ierr = DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 253 } 254 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 255 switch (numCoords) { 256 case 6: 257 case 12: /* Localized triangle */ 258 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); 259 break; 260 case 8: 261 case 16: /* Localized quadrilateral */ 262 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); 263 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); 264 break; 265 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords); 266 } 267 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 268 } 269 ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr); 270 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 271 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 272 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 273 } 274 if (Nf > 1) { 275 ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr); 276 ierr = ISDestroy(&fis);CHKERRQ(ierr); 277 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 278 } 279 } 280 PetscFunctionReturn(0); 281 } 282 283 static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 284 { 285 DM dm; 286 Vec locv; 287 const char *name; 288 PetscSection section; 289 PetscInt pStart, pEnd; 290 PetscInt numFields; 291 PetscViewerVTKFieldType ft; 292 PetscErrorCode ierr; 293 294 PetscFunctionBegin; 295 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 296 ierr = DMCreateLocalVector(dm, &locv);CHKERRQ(ierr); /* VTK viewer requires exclusive ownership of the vector */ 297 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 298 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 299 ierr = VecCopy(v, locv);CHKERRQ(ierr); 300 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 301 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 302 if (!numFields) { 303 ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 304 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 305 } else { 306 PetscInt f; 307 308 for (f = 0; f < numFields; f++) { 309 ierr = DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft);CHKERRQ(ierr); 310 if (ft == PETSC_VTK_INVALID) continue; 311 ierr = PetscObjectReference((PetscObject)locv);CHKERRQ(ierr); 312 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 313 } 314 ierr = VecDestroy(&locv);CHKERRQ(ierr); 315 } 316 PetscFunctionReturn(0); 317 } 318 319 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 320 { 321 DM dm; 322 PetscBool isvtk, ishdf5, isdraw, isglvis; 323 PetscErrorCode ierr; 324 325 PetscFunctionBegin; 326 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 327 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 328 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 329 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 330 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 331 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 332 if (isvtk || ishdf5 || isdraw || isglvis) { 333 PetscInt i,numFields; 334 PetscObject fe; 335 PetscBool fem = PETSC_FALSE; 336 Vec locv = v; 337 const char *name; 338 PetscInt step; 339 PetscReal time; 340 341 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 342 for (i=0; i<numFields; i++) { 343 ierr = DMGetField(dm, i, NULL, &fe);CHKERRQ(ierr); 344 if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; } 345 } 346 if (fem) { 347 PetscObject isZero; 348 349 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 350 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 351 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 352 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 353 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 354 ierr = VecCopy(v, locv);CHKERRQ(ierr); 355 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 356 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr); 357 } 358 if (isvtk) { 359 ierr = VecView_Plex_Local_VTK(locv, viewer);CHKERRQ(ierr); 360 } else if (ishdf5) { 361 #if defined(PETSC_HAVE_HDF5) 362 ierr = VecView_Plex_Local_HDF5_Internal(locv, viewer);CHKERRQ(ierr); 363 #else 364 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 365 #endif 366 } else if (isdraw) { 367 ierr = VecView_Plex_Local_Draw(locv, viewer);CHKERRQ(ierr); 368 } else if (isglvis) { 369 ierr = DMGetOutputSequenceNumber(dm, &step, NULL);CHKERRQ(ierr); 370 ierr = PetscViewerGLVisSetSnapId(viewer, step);CHKERRQ(ierr); 371 ierr = VecView_GLVis(locv, viewer);CHKERRQ(ierr); 372 } 373 if (fem) { 374 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 375 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 376 } 377 } else { 378 PetscBool isseq; 379 380 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 381 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 382 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 383 } 384 PetscFunctionReturn(0); 385 } 386 387 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 388 { 389 DM dm; 390 PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii; 391 PetscErrorCode ierr; 392 393 PetscFunctionBegin; 394 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 395 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 396 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 397 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 398 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 399 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 400 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 401 if (isvtk || isdraw || isglvis) { 402 Vec locv; 403 PetscObject isZero; 404 const char *name; 405 406 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 407 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 408 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 409 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 410 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 411 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 412 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 413 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 414 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 415 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 416 } else if (ishdf5) { 417 #if defined(PETSC_HAVE_HDF5) 418 ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 419 #else 420 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 421 #endif 422 } else if (isexodusii) { 423 #if defined(PETSC_HAVE_EXODUSII) 424 ierr = VecView_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 425 #else 426 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 427 #endif 428 } else { 429 PetscBool isseq; 430 431 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 432 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 433 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 434 } 435 PetscFunctionReturn(0); 436 } 437 438 PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 439 { 440 DM dm; 441 MPI_Comm comm; 442 PetscViewerFormat format; 443 Vec v; 444 PetscBool isvtk, ishdf5; 445 PetscErrorCode ierr; 446 447 PetscFunctionBegin; 448 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 449 ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 450 if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 451 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 452 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 453 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 454 if (format == PETSC_VIEWER_NATIVE) { 455 /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 456 /* this need a better fix */ 457 if (dm->useNatural) { 458 if (dm->sfNatural) { 459 const char *vecname; 460 PetscInt n, nroots; 461 462 ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr); 463 ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 464 if (n == nroots) { 465 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 466 ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 467 ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 468 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 469 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 470 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 471 } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 472 } else v = originalv; 473 } else v = originalv; 474 475 if (ishdf5) { 476 #if defined(PETSC_HAVE_HDF5) 477 ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 478 #else 479 SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 480 #endif 481 } else if (isvtk) { 482 SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 483 } else { 484 PetscBool isseq; 485 486 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 487 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 488 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 489 } 490 if (v != originalv) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 491 PetscFunctionReturn(0); 492 } 493 494 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 495 { 496 DM dm; 497 PetscBool ishdf5; 498 PetscErrorCode ierr; 499 500 PetscFunctionBegin; 501 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 502 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 503 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 504 if (ishdf5) { 505 DM dmBC; 506 Vec gv; 507 const char *name; 508 509 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 510 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 511 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 512 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 513 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 514 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 515 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 516 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 517 } else { 518 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 519 } 520 PetscFunctionReturn(0); 521 } 522 523 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 524 { 525 DM dm; 526 PetscBool ishdf5,isexodusii; 527 PetscErrorCode ierr; 528 529 PetscFunctionBegin; 530 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 531 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 532 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 533 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 534 if (ishdf5) { 535 #if defined(PETSC_HAVE_HDF5) 536 ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 537 #else 538 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 539 #endif 540 } else if (isexodusii) { 541 #if defined(PETSC_HAVE_EXODUSII) 542 ierr = VecLoad_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 543 #else 544 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 545 #endif 546 } else { 547 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 548 } 549 PetscFunctionReturn(0); 550 } 551 552 PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 553 { 554 DM dm; 555 PetscViewerFormat format; 556 PetscBool ishdf5; 557 PetscErrorCode ierr; 558 559 PetscFunctionBegin; 560 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 561 if (!dm) SETERRQ(PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 562 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 563 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 564 if (format == PETSC_VIEWER_NATIVE) { 565 if (dm->useNatural) { 566 if (dm->sfNatural) { 567 if (ishdf5) { 568 #if defined(PETSC_HAVE_HDF5) 569 Vec v; 570 const char *vecname; 571 572 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 573 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 574 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 575 ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 576 ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 577 ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 578 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 579 #else 580 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 581 #endif 582 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 583 } 584 } else { 585 ierr = VecLoad_Default(originalv, viewer);CHKERRQ(ierr); 586 } 587 } 588 PetscFunctionReturn(0); 589 } 590 591 PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 592 { 593 PetscSection coordSection; 594 Vec coordinates; 595 DMLabel depthLabel, celltypeLabel; 596 const char *name[4]; 597 const PetscScalar *a; 598 PetscInt dim, pStart, pEnd, cStart, cEnd, c; 599 PetscErrorCode ierr; 600 601 PetscFunctionBegin; 602 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 603 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 604 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 605 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 606 ierr = DMPlexGetCellTypeLabel(dm, &celltypeLabel);CHKERRQ(ierr); 607 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 608 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 609 ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 610 name[0] = "vertex"; 611 name[1] = "edge"; 612 name[dim-1] = "face"; 613 name[dim] = "cell"; 614 for (c = cStart; c < cEnd; ++c) { 615 PetscInt *closure = NULL; 616 PetscInt closureSize, cl, ct; 617 618 ierr = DMLabelGetValue(celltypeLabel, c, &ct);CHKERRQ(ierr); 619 ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]);CHKERRQ(ierr); 620 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 621 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 622 for (cl = 0; cl < closureSize*2; cl += 2) { 623 PetscInt point = closure[cl], depth, dof, off, d, p; 624 625 if ((point < pStart) || (point >= pEnd)) continue; 626 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 627 if (!dof) continue; 628 ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 629 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 630 ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr); 631 for (p = 0; p < dof/dim; ++p) { 632 ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 633 for (d = 0; d < dim; ++d) { 634 if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 635 ierr = PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 636 } 637 ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 638 } 639 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 640 } 641 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 642 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 643 } 644 ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 645 PetscFunctionReturn(0); 646 } 647 648 static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 649 { 650 DM_Plex *mesh = (DM_Plex*) dm->data; 651 DM cdm; 652 PetscSection coordSection; 653 Vec coordinates; 654 PetscViewerFormat format; 655 PetscErrorCode ierr; 656 657 PetscFunctionBegin; 658 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 659 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 660 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 661 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 662 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 663 const char *name; 664 PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 665 PetscInt pStart, pEnd, p, numLabels, l; 666 PetscMPIInt rank, size; 667 668 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 669 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 670 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 671 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 672 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 673 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 674 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 675 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 676 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 677 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 678 ierr = PetscViewerASCIIPrintf(viewer, "Supports:\n", name);CHKERRQ(ierr); 679 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 680 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize);CHKERRQ(ierr); 681 for (p = pStart; p < pEnd; ++p) { 682 PetscInt dof, off, s; 683 684 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 685 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 686 for (s = off; s < off+dof; ++s) { 687 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 688 } 689 } 690 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 691 ierr = PetscViewerASCIIPrintf(viewer, "Cones:\n", name);CHKERRQ(ierr); 692 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize);CHKERRQ(ierr); 693 for (p = pStart; p < pEnd; ++p) { 694 PetscInt dof, off, c; 695 696 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 697 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 698 for (c = off; c < off+dof; ++c) { 699 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 700 } 701 } 702 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 703 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 704 if (coordSection && coordinates) { 705 ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr); 706 } 707 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 708 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 709 for (l = 0; l < numLabels; ++l) { 710 DMLabel label; 711 PetscBool isdepth; 712 const char *name; 713 714 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 715 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 716 if (isdepth) continue; 717 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 718 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 719 } 720 if (size > 1) { 721 PetscSF sf; 722 723 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 724 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 725 } 726 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 727 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 728 const char *name, *color; 729 const char *defcolors[3] = {"gray", "orange", "green"}; 730 const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 731 char lname[PETSC_MAX_PATH_LEN]; 732 PetscReal scale = 2.0; 733 PetscReal tikzscale = 1.0; 734 PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 735 double tcoords[3]; 736 PetscScalar *coords; 737 PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 738 PetscMPIInt rank, size; 739 char **names, **colors, **lcolors; 740 PetscBool flg, lflg; 741 PetscBT wp = NULL; 742 PetscInt pEnd, pStart; 743 744 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 745 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 746 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 747 numLabels = PetscMax(numLabels, 10); 748 numColors = 10; 749 numLColors = 10; 750 ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 751 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 752 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL);CHKERRQ(ierr); 753 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 754 for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 755 for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 756 n = 4; 757 ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg);CHKERRQ(ierr); 758 if (flg && n != dim+1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 759 ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg);CHKERRQ(ierr); 760 if (flg && n != dim+1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 761 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 762 if (!useLabels) numLabels = 0; 763 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 764 if (!useColors) { 765 numColors = 3; 766 for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 767 } 768 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 769 if (!useColors) { 770 numLColors = 4; 771 for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 772 } 773 ierr = PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg);CHKERRQ(ierr); 774 plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 775 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg);CHKERRQ(ierr); 776 if (flg && plotEdges && depth < dim) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 777 if (depth < dim) plotEdges = PETSC_FALSE; 778 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL);CHKERRQ(ierr); 779 780 /* filter points with labelvalue != labeldefaultvalue */ 781 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 782 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 783 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 784 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 785 if (lflg) { 786 DMLabel lbl; 787 788 ierr = DMGetLabel(dm, lname, &lbl);CHKERRQ(ierr); 789 if (lbl) { 790 PetscInt val, defval; 791 792 ierr = DMLabelGetDefaultValue(lbl, &defval);CHKERRQ(ierr); 793 ierr = PetscBTCreate(pEnd-pStart, &wp);CHKERRQ(ierr); 794 for (c = pStart; c < pEnd; c++) { 795 PetscInt *closure = NULL; 796 PetscInt closureSize; 797 798 ierr = DMLabelGetValue(lbl, c, &val);CHKERRQ(ierr); 799 if (val == defval) continue; 800 801 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 802 for (p = 0; p < closureSize*2; p += 2) { 803 ierr = PetscBTSet(wp, closure[p] - pStart);CHKERRQ(ierr); 804 } 805 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 806 } 807 } 808 } 809 810 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 811 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 812 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 813 ierr = PetscViewerASCIIPrintf(viewer, "\ 814 \\documentclass[tikz]{standalone}\n\n\ 815 \\usepackage{pgflibraryshapes}\n\ 816 \\usetikzlibrary{backgrounds}\n\ 817 \\usetikzlibrary{arrows}\n\ 818 \\begin{document}\n");CHKERRQ(ierr); 819 if (size > 1) { 820 ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 821 for (p = 0; p < size; ++p) { 822 if (p > 0 && p == size-1) { 823 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 824 } else if (p > 0) { 825 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 826 } 827 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 828 } 829 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 830 } 831 if (drawHasse) { 832 PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart)); 833 834 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%D}\n", vStart);CHKERRQ(ierr); 835 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%D}\n", vEnd-1);CHKERRQ(ierr); 836 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%D}\n", vEnd-vStart);CHKERRQ(ierr); 837 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.);CHKERRQ(ierr); 838 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%D}\n", eStart);CHKERRQ(ierr); 839 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%D}\n", eEnd-1);CHKERRQ(ierr); 840 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.);CHKERRQ(ierr); 841 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%D}\n", eEnd-eStart);CHKERRQ(ierr); 842 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%D}\n", cStart);CHKERRQ(ierr); 843 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%D}\n", cEnd-1);CHKERRQ(ierr); 844 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%D}\n", cEnd-cStart);CHKERRQ(ierr); 845 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.);CHKERRQ(ierr); 846 } 847 ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale);CHKERRQ(ierr); 848 849 /* Plot vertices */ 850 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 851 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 852 for (v = vStart; v < vEnd; ++v) { 853 PetscInt off, dof, d; 854 PetscBool isLabeled = PETSC_FALSE; 855 856 if (wp && !PetscBTLookup(wp,v - pStart)) continue; 857 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 858 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 859 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 860 if (PetscUnlikely(dof > 3)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 861 for (d = 0; d < dof; ++d) { 862 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 863 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 864 } 865 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 866 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 867 for (d = 0; d < dof; ++d) { 868 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 869 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]);CHKERRQ(ierr); 870 } 871 if (drawHasse) color = colors[0%numColors]; 872 else color = colors[rank%numColors]; 873 for (l = 0; l < numLabels; ++l) { 874 PetscInt val; 875 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 876 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 877 } 878 if (drawNumbers[0]) { 879 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 880 } else if (drawColors[0]) { 881 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 882 } else { 883 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", v, rank);CHKERRQ(ierr); 884 } 885 } 886 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 887 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 888 /* Plot edges */ 889 if (plotEdges) { 890 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 891 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 892 for (e = eStart; e < eEnd; ++e) { 893 const PetscInt *cone; 894 PetscInt coneSize, offA, offB, dof, d; 895 896 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 897 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 898 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 899 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 900 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 901 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 902 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 903 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 904 for (d = 0; d < dof; ++d) { 905 tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 906 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 907 } 908 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 909 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 910 for (d = 0; d < dof; ++d) { 911 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 912 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr); 913 } 914 if (drawHasse) color = colors[1%numColors]; 915 else color = colors[rank%numColors]; 916 for (l = 0; l < numLabels; ++l) { 917 PetscInt val; 918 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 919 if (val >= 0) {color = lcolors[l%numLColors]; break;} 920 } 921 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 922 } 923 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 924 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 925 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 926 } 927 /* Plot cells */ 928 if (dim == 3 || !drawNumbers[1]) { 929 for (e = eStart; e < eEnd; ++e) { 930 const PetscInt *cone; 931 932 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 933 color = colors[rank%numColors]; 934 for (l = 0; l < numLabels; ++l) { 935 PetscInt val; 936 ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 937 if (val >= 0) {color = lcolors[l%numLColors]; break;} 938 } 939 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 940 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 941 } 942 } else { 943 DMPolytopeType ct; 944 945 /* Drawing a 2D polygon */ 946 for (c = cStart; c < cEnd; ++c) { 947 if (wp && !PetscBTLookup(wp, c - pStart)) continue; 948 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 949 if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || 950 ct == DM_POLYTOPE_TRI_PRISM_TENSOR || 951 ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 952 const PetscInt *cone; 953 PetscInt coneSize, e; 954 955 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 956 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 957 for (e = 0; e < coneSize; ++e) { 958 const PetscInt *econe; 959 960 ierr = DMPlexGetCone(dm, cone[e], &econe);CHKERRQ(ierr); 961 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); 962 } 963 } else { 964 PetscInt *closure = NULL; 965 PetscInt closureSize, Nv = 0, v; 966 967 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 968 for (p = 0; p < closureSize*2; p += 2) { 969 const PetscInt point = closure[p]; 970 971 if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 972 } 973 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 974 for (v = 0; v <= Nv; ++v) { 975 const PetscInt vertex = closure[v%Nv]; 976 977 if (v > 0) { 978 if (plotEdges) { 979 const PetscInt *edge; 980 PetscInt endpoints[2], ne; 981 982 endpoints[0] = closure[v-1]; endpoints[1] = vertex; 983 ierr = DMPlexGetJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr); 984 if (ne != 1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %D, %D", endpoints[0], endpoints[1]); 985 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d) -- ", edge[0], rank);CHKERRQ(ierr); 986 ierr = DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr); 987 } else { 988 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr); 989 } 990 } 991 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", vertex, rank);CHKERRQ(ierr); 992 } 993 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ";\n");CHKERRQ(ierr); 994 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 995 } 996 } 997 } 998 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 999 for (c = cStart; c < cEnd; ++c) { 1000 double ccoords[3] = {0.0, 0.0, 0.0}; 1001 PetscBool isLabeled = PETSC_FALSE; 1002 PetscInt *closure = NULL; 1003 PetscInt closureSize, dof, d, n = 0; 1004 1005 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 1006 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1007 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 1008 for (p = 0; p < closureSize*2; p += 2) { 1009 const PetscInt point = closure[p]; 1010 PetscInt off; 1011 1012 if ((point < vStart) || (point >= vEnd)) continue; 1013 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 1014 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 1015 for (d = 0; d < dof; ++d) { 1016 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1017 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1018 } 1019 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1020 if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1021 for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 1022 ++n; 1023 } 1024 for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 1025 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1026 for (d = 0; d < dof; ++d) { 1027 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 1028 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]);CHKERRQ(ierr); 1029 } 1030 if (drawHasse) color = colors[depth%numColors]; 1031 else color = colors[rank%numColors]; 1032 for (l = 0; l < numLabels; ++l) { 1033 PetscInt val; 1034 ierr = DMGetLabelValue(dm, names[l], c, &val);CHKERRQ(ierr); 1035 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 1036 } 1037 if (drawNumbers[dim]) { 1038 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c);CHKERRQ(ierr); 1039 } else if (drawColors[dim]) { 1040 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 1041 } else { 1042 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", c, rank);CHKERRQ(ierr); 1043 } 1044 } 1045 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1046 if (drawHasse) { 1047 color = colors[depth%numColors]; 1048 ierr = PetscViewerASCIIPrintf(viewer, "%% Cells\n");CHKERRQ(ierr); 1049 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n");CHKERRQ(ierr); 1050 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1051 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); 1052 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1053 1054 color = colors[1%numColors]; 1055 ierr = PetscViewerASCIIPrintf(viewer, "%% Edges\n");CHKERRQ(ierr); 1056 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n");CHKERRQ(ierr); 1057 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1058 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); 1059 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1060 1061 color = colors[0%numColors]; 1062 ierr = PetscViewerASCIIPrintf(viewer, "%% Vertices\n");CHKERRQ(ierr); 1063 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n");CHKERRQ(ierr); 1064 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1065 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); 1066 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1067 1068 for (p = pStart; p < pEnd; ++p) { 1069 const PetscInt *cone; 1070 PetscInt coneSize, cp; 1071 1072 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1073 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1074 for (cp = 0; cp < coneSize; ++cp) { 1075 ierr = PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%D_%d) -- (%D_%d);\n", cone[cp], rank, p, rank);CHKERRQ(ierr); 1076 } 1077 } 1078 } 1079 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1080 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 1081 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 1082 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 1083 for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 1084 for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 1085 for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 1086 ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 1087 ierr = PetscBTDestroy(&wp);CHKERRQ(ierr); 1088 } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 1089 Vec cown,acown; 1090 VecScatter sct; 1091 ISLocalToGlobalMapping g2l; 1092 IS gid,acis; 1093 MPI_Comm comm,ncomm = MPI_COMM_NULL; 1094 MPI_Group ggroup,ngroup; 1095 PetscScalar *array,nid; 1096 const PetscInt *idxs; 1097 PetscInt *idxs2,*start,*adjacency,*work; 1098 PetscInt64 lm[3],gm[3]; 1099 PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 1100 PetscMPIInt d1,d2,rank; 1101 1102 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1103 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 1104 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1105 ierr = MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm);CHKERRMPI(ierr); 1106 #endif 1107 if (ncomm != MPI_COMM_NULL) { 1108 ierr = MPI_Comm_group(comm,&ggroup);CHKERRMPI(ierr); 1109 ierr = MPI_Comm_group(ncomm,&ngroup);CHKERRMPI(ierr); 1110 d1 = 0; 1111 ierr = MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2);CHKERRMPI(ierr); 1112 nid = d2; 1113 ierr = MPI_Group_free(&ggroup);CHKERRMPI(ierr); 1114 ierr = MPI_Group_free(&ngroup);CHKERRMPI(ierr); 1115 ierr = MPI_Comm_free(&ncomm);CHKERRMPI(ierr); 1116 } else nid = 0.0; 1117 1118 /* Get connectivity */ 1119 ierr = DMPlexGetVTKCellHeight(dm,&cellHeight);CHKERRQ(ierr); 1120 ierr = DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid);CHKERRQ(ierr); 1121 1122 /* filter overlapped local cells */ 1123 ierr = DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd);CHKERRQ(ierr); 1124 ierr = ISGetIndices(gid,&idxs);CHKERRQ(ierr); 1125 ierr = ISGetLocalSize(gid,&cum);CHKERRQ(ierr); 1126 ierr = PetscMalloc1(cum,&idxs2);CHKERRQ(ierr); 1127 for (c = cStart, cum = 0; c < cEnd; c++) { 1128 if (idxs[c-cStart] < 0) continue; 1129 idxs2[cum++] = idxs[c-cStart]; 1130 } 1131 ierr = ISRestoreIndices(gid,&idxs);CHKERRQ(ierr); 1132 if (numVertices != cum) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum); 1133 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1134 ierr = ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid);CHKERRQ(ierr); 1135 1136 /* support for node-aware cell locality */ 1137 ierr = ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis);CHKERRQ(ierr); 1138 ierr = VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown);CHKERRQ(ierr); 1139 ierr = VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown);CHKERRQ(ierr); 1140 ierr = VecGetArray(cown,&array);CHKERRQ(ierr); 1141 for (c = 0; c < numVertices; c++) array[c] = nid; 1142 ierr = VecRestoreArray(cown,&array);CHKERRQ(ierr); 1143 ierr = VecScatterCreate(cown,acis,acown,NULL,&sct);CHKERRQ(ierr); 1144 ierr = VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1145 ierr = VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1146 ierr = ISDestroy(&acis);CHKERRQ(ierr); 1147 ierr = VecScatterDestroy(&sct);CHKERRQ(ierr); 1148 ierr = VecDestroy(&cown);CHKERRQ(ierr); 1149 1150 /* compute edgeCut */ 1151 for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 1152 ierr = PetscMalloc1(cum,&work);CHKERRQ(ierr); 1153 ierr = ISLocalToGlobalMappingCreateIS(gid,&g2l);CHKERRQ(ierr); 1154 ierr = ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 1155 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1156 ierr = VecGetArray(acown,&array);CHKERRQ(ierr); 1157 for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 1158 PetscInt totl; 1159 1160 totl = start[c+1]-start[c]; 1161 ierr = ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work);CHKERRQ(ierr); 1162 for (i = 0; i < totl; i++) { 1163 if (work[i] < 0) { 1164 ect += 1; 1165 ectn += (array[i + start[c]] != nid) ? 0 : 1; 1166 } 1167 } 1168 } 1169 ierr = PetscFree(work);CHKERRQ(ierr); 1170 ierr = VecRestoreArray(acown,&array);CHKERRQ(ierr); 1171 lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 1172 lm[1] = -numVertices; 1173 ierr = MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm);CHKERRMPI(ierr); 1174 ierr = PetscViewerASCIIPrintf(viewer," Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]);CHKERRQ(ierr); 1175 lm[0] = ect; /* edgeCut */ 1176 lm[1] = ectn; /* node-aware edgeCut */ 1177 lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 1178 ierr = MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr); 1179 ierr = PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]);CHKERRQ(ierr); 1180 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1181 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); 1182 #else 1183 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0);CHKERRQ(ierr); 1184 #endif 1185 ierr = ISLocalToGlobalMappingDestroy(&g2l);CHKERRQ(ierr); 1186 ierr = PetscFree(start);CHKERRQ(ierr); 1187 ierr = PetscFree(adjacency);CHKERRQ(ierr); 1188 ierr = VecDestroy(&acown);CHKERRQ(ierr); 1189 } else { 1190 const char *name; 1191 PetscInt *sizes, *hybsizes, *ghostsizes; 1192 PetscInt locDepth, depth, cellHeight, dim, d; 1193 PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1194 PetscInt numLabels, l; 1195 DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1196 MPI_Comm comm; 1197 PetscMPIInt size, rank; 1198 1199 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1200 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1201 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1202 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1203 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 1204 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 1205 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1206 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1207 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 1208 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 1209 ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRMPI(ierr); 1210 ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr); 1211 gcNum = gcEnd - gcStart; 1212 ierr = PetscCalloc3(size,&sizes,size,&hybsizes,size,&ghostsizes);CHKERRQ(ierr); 1213 for (d = 0; d <= depth; d++) { 1214 PetscInt Nc[2] = {0, 0}, ict; 1215 1216 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 1217 if (pStart < pEnd) {ierr = DMPlexGetCellType(dm, pStart, &ct0);CHKERRQ(ierr);} 1218 ict = ct0; 1219 ierr = MPI_Bcast(&ict, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1220 ct0 = (DMPolytopeType) ict; 1221 for (p = pStart; p < pEnd; ++p) { 1222 DMPolytopeType ct; 1223 1224 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 1225 if (ct == ct0) ++Nc[0]; 1226 else ++Nc[1]; 1227 } 1228 ierr = MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1229 ierr = MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1230 if (d == depth) {ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);} 1231 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", (depth == 1) && d ? dim : d);CHKERRQ(ierr); 1232 for (p = 0; p < size; ++p) { 1233 if (!rank) { 1234 ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]);CHKERRQ(ierr); 1235 if (hybsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]);CHKERRQ(ierr);} 1236 if (ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);} 1237 } 1238 } 1239 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 1240 } 1241 ierr = PetscFree3(sizes,hybsizes,ghostsizes);CHKERRQ(ierr); 1242 { 1243 const PetscReal *maxCell; 1244 const PetscReal *L; 1245 const DMBoundaryType *bd; 1246 PetscBool per, localized; 1247 1248 ierr = DMGetPeriodicity(dm, &per, &maxCell, &L, &bd);CHKERRQ(ierr); 1249 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 1250 if (per) { 1251 ierr = PetscViewerASCIIPrintf(viewer, "Periodic mesh (");CHKERRQ(ierr); 1252 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1253 for (d = 0; d < dim; ++d) { 1254 if (bd && d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1255 if (bd) {ierr = PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]]);CHKERRQ(ierr);} 1256 } 1257 ierr = PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized");CHKERRQ(ierr); 1258 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1259 } 1260 } 1261 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 1262 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 1263 for (l = 0; l < numLabels; ++l) { 1264 DMLabel label; 1265 const char *name; 1266 IS valueIS; 1267 const PetscInt *values; 1268 PetscInt numValues, v; 1269 1270 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 1271 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1272 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 1273 ierr = PetscViewerASCIIPrintf(viewer, " %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr); 1274 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 1275 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 1276 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1277 for (v = 0; v < numValues; ++v) { 1278 PetscInt size; 1279 1280 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 1281 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1282 ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr); 1283 } 1284 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 1285 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1286 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 1287 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 1288 } 1289 { 1290 char **labelNames; 1291 PetscInt Nl = numLabels; 1292 PetscBool flg; 1293 1294 ierr = PetscMalloc1(Nl, &labelNames);CHKERRQ(ierr); 1295 ierr = PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg);CHKERRQ(ierr); 1296 for (l = 0; l < Nl; ++l) { 1297 DMLabel label; 1298 1299 ierr = DMHasLabel(dm, labelNames[l], &flg);CHKERRQ(ierr); 1300 if (flg) { 1301 ierr = DMGetLabel(dm, labelNames[l], &label);CHKERRQ(ierr); 1302 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 1303 } 1304 ierr = PetscFree(labelNames[l]);CHKERRQ(ierr); 1305 } 1306 ierr = PetscFree(labelNames);CHKERRQ(ierr); 1307 } 1308 /* If no fields are specified, people do not want to see adjacency */ 1309 if (dm->Nf) { 1310 PetscInt f; 1311 1312 for (f = 0; f < dm->Nf; ++f) { 1313 const char *name; 1314 1315 ierr = PetscObjectGetName(dm->fields[f].disc, &name);CHKERRQ(ierr); 1316 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Field %s:\n", name);CHKERRQ(ierr);} 1317 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1318 if (dm->fields[f].label) {ierr = DMLabelView(dm->fields[f].label, viewer);CHKERRQ(ierr);} 1319 if (dm->fields[f].adjacency[0]) { 1320 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n");CHKERRQ(ierr);} 1321 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM\n");CHKERRQ(ierr);} 1322 } else { 1323 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FEM\n");CHKERRQ(ierr);} 1324 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n");CHKERRQ(ierr);} 1325 } 1326 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1327 } 1328 } 1329 ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr); 1330 if (cdm) { 1331 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1332 ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr); 1333 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1334 } 1335 } 1336 PetscFunctionReturn(0); 1337 } 1338 1339 static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1340 { 1341 DMPolytopeType ct; 1342 PetscMPIInt rank; 1343 PetscErrorCode ierr; 1344 1345 PetscFunctionBegin; 1346 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1347 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1348 switch (ct) { 1349 case DM_POLYTOPE_TRIANGLE: 1350 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1351 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1352 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1353 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1354 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1355 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1356 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1357 break; 1358 case DM_POLYTOPE_QUADRILATERAL: 1359 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1360 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1361 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1362 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1363 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1364 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1365 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1366 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1367 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1368 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1369 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1370 ierr = PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1371 break; 1372 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1373 } 1374 PetscFunctionReturn(0); 1375 } 1376 1377 static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1378 { 1379 DMPolytopeType ct; 1380 PetscReal centroid[2] = {0., 0.}; 1381 PetscMPIInt rank; 1382 PetscInt fillColor, v, e, d; 1383 PetscErrorCode ierr; 1384 1385 PetscFunctionBegin; 1386 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1387 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1388 fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2; 1389 switch (ct) { 1390 case DM_POLYTOPE_TRIANGLE: 1391 { 1392 PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1393 1394 for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;} 1395 for (e = 0; e < 3; ++e) { 1396 refCoords[0] = refVertices[e*2+0]; 1397 refCoords[1] = refVertices[e*2+1]; 1398 for (d = 1; d <= edgeDiv; ++d) { 1399 refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv; 1400 refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv; 1401 } 1402 ierr = DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords);CHKERRQ(ierr); 1403 for (d = 0; d < edgeDiv; ++d) { 1404 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); 1405 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); 1406 } 1407 } 1408 } 1409 break; 1410 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1411 } 1412 PetscFunctionReturn(0); 1413 } 1414 1415 static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1416 { 1417 PetscDraw draw; 1418 DM cdm; 1419 PetscSection coordSection; 1420 Vec coordinates; 1421 const PetscScalar *coords; 1422 PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1423 PetscReal *refCoords, *edgeCoords; 1424 PetscBool isnull, drawAffine = PETSC_TRUE; 1425 PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1426 PetscErrorCode ierr; 1427 1428 PetscFunctionBegin; 1429 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 1430 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim); 1431 ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL);CHKERRQ(ierr); 1432 if (!drawAffine) {ierr = PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords);CHKERRQ(ierr);} 1433 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 1434 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1435 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 1436 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1437 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1438 1439 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 1440 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 1441 if (isnull) PetscFunctionReturn(0); 1442 ierr = PetscDrawSetTitle(draw, "Mesh");CHKERRQ(ierr); 1443 1444 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 1445 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 1446 for (c = 0; c < N; c += dim) { 1447 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 1448 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1449 } 1450 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 1451 ierr = MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1452 ierr = MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1453 ierr = PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]);CHKERRQ(ierr); 1454 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 1455 1456 for (c = cStart; c < cEnd; ++c) { 1457 PetscScalar *coords = NULL; 1458 PetscInt numCoords; 1459 1460 ierr = DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords);CHKERRQ(ierr); 1461 if (drawAffine) { 1462 ierr = DMPlexDrawCell(dm, draw, c, coords);CHKERRQ(ierr); 1463 } else { 1464 ierr = DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords);CHKERRQ(ierr); 1465 } 1466 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 1467 } 1468 if (!drawAffine) {ierr = PetscFree2(refCoords, edgeCoords);CHKERRQ(ierr);} 1469 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1470 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 1471 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 1472 PetscFunctionReturn(0); 1473 } 1474 1475 #if defined(PETSC_HAVE_EXODUSII) 1476 #include <exodusII.h> 1477 #include <petscviewerexodusii.h> 1478 #endif 1479 1480 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1481 { 1482 PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1483 char name[PETSC_MAX_PATH_LEN]; 1484 PetscErrorCode ierr; 1485 1486 PetscFunctionBegin; 1487 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1488 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1489 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1490 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1491 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1492 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 1493 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 1494 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus);CHKERRQ(ierr); 1495 if (iascii) { 1496 PetscViewerFormat format; 1497 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1498 if (format == PETSC_VIEWER_ASCII_GLVIS) { 1499 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1500 } else { 1501 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 1502 } 1503 } else if (ishdf5) { 1504 #if defined(PETSC_HAVE_HDF5) 1505 ierr = DMPlexView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1506 #else 1507 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1508 #endif 1509 } else if (isvtk) { 1510 ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr); 1511 } else if (isdraw) { 1512 ierr = DMPlexView_Draw(dm, viewer);CHKERRQ(ierr); 1513 } else if (isglvis) { 1514 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1515 #if defined(PETSC_HAVE_EXODUSII) 1516 } else if (isexodus) { 1517 /* 1518 exodusII requires that all sets be part of exactly one cell set. 1519 If the dm does not have a "Cell Sets" label defined, we create one 1520 with ID 1, containig all cells. 1521 Note that if the Cell Sets label is defined but does not cover all cells, 1522 we may still have a problem. This should probably be checked here or in the viewer; 1523 */ 1524 PetscInt numCS; 1525 ierr = DMGetLabelSize(dm,"Cell Sets",&numCS);CHKERRQ(ierr); 1526 if (!numCS) { 1527 PetscInt cStart, cEnd, c; 1528 ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr); 1529 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1530 for (c = cStart; c < cEnd; ++c) {ierr = DMSetLabelValue(dm, "Cell Sets", c, 1);CHKERRQ(ierr);} 1531 } 1532 ierr = DMView_PlexExodusII(dm, viewer);CHKERRQ(ierr); 1533 #endif 1534 } else { 1535 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1536 } 1537 /* Optionally view the partition */ 1538 ierr = PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg);CHKERRQ(ierr); 1539 if (flg) { 1540 Vec ranks; 1541 ierr = DMPlexCreateRankField(dm, &ranks);CHKERRQ(ierr); 1542 ierr = VecView(ranks, viewer);CHKERRQ(ierr); 1543 ierr = VecDestroy(&ranks);CHKERRQ(ierr); 1544 } 1545 /* Optionally view a label */ 1546 ierr = PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg);CHKERRQ(ierr); 1547 if (flg) { 1548 DMLabel label; 1549 Vec val; 1550 1551 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1552 if (!label) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 1553 ierr = DMPlexCreateLabelField(dm, label, &val);CHKERRQ(ierr); 1554 ierr = VecView(val, viewer);CHKERRQ(ierr); 1555 ierr = VecDestroy(&val);CHKERRQ(ierr); 1556 } 1557 PetscFunctionReturn(0); 1558 } 1559 1560 /*@ 1561 DMPlexTopologyView - Saves a DMPlex topology into a file 1562 1563 Collective on DM 1564 1565 Input Parameters: 1566 + dm - The DM whose topology is to be saved 1567 - viewer - The PetscViewer for saving 1568 1569 Level: advanced 1570 1571 .seealso: DMView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexTopologyLoad() 1572 @*/ 1573 PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 1574 { 1575 PetscBool ishdf5; 1576 PetscErrorCode ierr; 1577 1578 PetscFunctionBegin; 1579 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1580 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1581 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1582 if (ishdf5) { 1583 #if defined(PETSC_HAVE_HDF5) 1584 PetscViewerFormat format; 1585 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1586 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1587 IS globalPointNumbering; 1588 1589 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1590 ierr = DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1591 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1592 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 1593 #else 1594 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1595 #endif 1596 } 1597 PetscFunctionReturn(0); 1598 } 1599 1600 /*@ 1601 DMPlexCoordinatesView - Saves DMPlex coordinates into a file 1602 1603 Collective on DM 1604 1605 Input Parameters: 1606 + dm - The DM whose coordinates are to be saved 1607 - viewer - The PetscViewer for saving 1608 1609 Level: advanced 1610 1611 .seealso: DMView(), DMPlexTopologyView(), DMPlexLabelsView(), DMPlexCoordinatesLoad() 1612 @*/ 1613 PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 1614 { 1615 PetscBool ishdf5; 1616 PetscErrorCode ierr; 1617 1618 PetscFunctionBegin; 1619 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1620 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1621 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1622 if (ishdf5) { 1623 #if defined(PETSC_HAVE_HDF5) 1624 PetscViewerFormat format; 1625 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1626 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1627 ierr = DMPlexCoordinatesView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1628 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1629 #else 1630 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1631 #endif 1632 } 1633 PetscFunctionReturn(0); 1634 } 1635 1636 /*@ 1637 DMPlexLabelsView - Saves DMPlex labels into a file 1638 1639 Collective on DM 1640 1641 Input Parameters: 1642 + dm - The DM whose labels are to be saved 1643 - viewer - The PetscViewer for saving 1644 1645 Level: advanced 1646 1647 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsLoad() 1648 @*/ 1649 PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1650 { 1651 PetscBool ishdf5; 1652 PetscErrorCode ierr; 1653 1654 PetscFunctionBegin; 1655 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1656 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1657 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1658 if (ishdf5) { 1659 #if defined(PETSC_HAVE_HDF5) 1660 IS globalPointNumbering; 1661 PetscViewerFormat format; 1662 1663 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1664 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1665 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1666 ierr = DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1667 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1668 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1669 #else 1670 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1671 #endif 1672 } 1673 PetscFunctionReturn(0); 1674 } 1675 1676 /*@ 1677 DMPlexSectionView - Saves a section associated with a DMPlex 1678 1679 Collective on DM 1680 1681 Input Parameters: 1682 + dm - The DM that contains the topology on which the section to be saved is defined 1683 . viewer - The PetscViewer for saving 1684 - sectiondm - The DM that contains the section to be saved 1685 1686 Level: advanced 1687 1688 Notes: 1689 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. 1690 1691 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. 1692 1693 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexGlobalVectorView(), DMPlexLocalVectorView(), PetscSectionView(), DMPlexSectionLoad() 1694 @*/ 1695 PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1696 { 1697 PetscBool ishdf5; 1698 PetscErrorCode ierr; 1699 1700 PetscFunctionBegin; 1701 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1702 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1703 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1704 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 1705 if (ishdf5) { 1706 #if defined(PETSC_HAVE_HDF5) 1707 ierr = DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm);CHKERRQ(ierr); 1708 #else 1709 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1710 #endif 1711 } 1712 PetscFunctionReturn(0); 1713 } 1714 1715 /*@ 1716 DMPlexGlobalVectorView - Saves a global vector 1717 1718 Collective on DM 1719 1720 Input Parameters: 1721 + dm - The DM that represents the topology 1722 . viewer - The PetscViewer to save data with 1723 . sectiondm - The DM that contains the global section on which vec is defined 1724 - vec - The global vector to be saved 1725 1726 Level: advanced 1727 1728 Notes: 1729 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. 1730 1731 Typical calling sequence 1732 $ DMCreate(PETSC_COMM_WORLD, &dm); 1733 $ DMSetType(dm, DMPLEX); 1734 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1735 $ DMClone(dm, §iondm); 1736 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1737 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1738 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1739 $ PetscSectionSetChart(section, pStart, pEnd); 1740 $ PetscSectionSetUp(section); 1741 $ DMSetLocalSection(sectiondm, section); 1742 $ PetscSectionDestroy(§ion); 1743 $ DMGetGlobalVector(sectiondm, &vec); 1744 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1745 $ DMPlexTopologyView(dm, viewer); 1746 $ DMPlexSectionView(dm, viewer, sectiondm); 1747 $ DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 1748 $ DMRestoreGlobalVector(sectiondm, &vec); 1749 $ DMDestroy(§iondm); 1750 $ DMDestroy(&dm); 1751 1752 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexLocalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1753 @*/ 1754 PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1755 { 1756 PetscBool ishdf5; 1757 PetscErrorCode ierr; 1758 1759 PetscFunctionBegin; 1760 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1761 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1762 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1763 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1764 /* Check consistency */ 1765 { 1766 PetscSection section; 1767 PetscBool includesConstraints; 1768 PetscInt m, m1; 1769 1770 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1771 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 1772 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1773 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1774 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1775 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 1776 } 1777 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1778 if (ishdf5) { 1779 #if defined(PETSC_HAVE_HDF5) 1780 ierr = DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1781 #else 1782 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1783 #endif 1784 } 1785 PetscFunctionReturn(0); 1786 } 1787 1788 /*@ 1789 DMPlexLocalVectorView - Saves a local vector 1790 1791 Collective on DM 1792 1793 Input Parameters: 1794 + dm - The DM that represents the topology 1795 . viewer - The PetscViewer to save data with 1796 . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm 1797 - vec - The local vector to be saved 1798 1799 Level: advanced 1800 1801 Notes: 1802 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. 1803 1804 Typical calling sequence 1805 $ DMCreate(PETSC_COMM_WORLD, &dm); 1806 $ DMSetType(dm, DMPLEX); 1807 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1808 $ DMClone(dm, §iondm); 1809 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1810 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1811 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1812 $ PetscSectionSetChart(section, pStart, pEnd); 1813 $ PetscSectionSetUp(section); 1814 $ DMSetLocalSection(sectiondm, section); 1815 $ DMGetLocalVector(sectiondm, &vec); 1816 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1817 $ DMPlexTopologyView(dm, viewer); 1818 $ DMPlexSectionView(dm, viewer, sectiondm); 1819 $ DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 1820 $ DMRestoreLocalVector(sectiondm, &vec); 1821 $ DMDestroy(§iondm); 1822 $ DMDestroy(&dm); 1823 1824 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexGlobalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1825 @*/ 1826 PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1827 { 1828 PetscBool ishdf5; 1829 PetscErrorCode ierr; 1830 1831 PetscFunctionBegin; 1832 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1833 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1834 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1835 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1836 /* Check consistency */ 1837 { 1838 PetscSection section; 1839 PetscBool includesConstraints; 1840 PetscInt m, m1; 1841 1842 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1843 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 1844 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1845 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1846 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1847 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 1848 } 1849 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1850 if (ishdf5) { 1851 #if defined(PETSC_HAVE_HDF5) 1852 ierr = DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1853 #else 1854 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1855 #endif 1856 } 1857 PetscFunctionReturn(0); 1858 } 1859 1860 PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 1861 { 1862 PetscBool ishdf5; 1863 PetscErrorCode ierr; 1864 1865 PetscFunctionBegin; 1866 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1867 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1868 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1869 if (ishdf5) { 1870 #if defined(PETSC_HAVE_HDF5) 1871 PetscViewerFormat format; 1872 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1873 if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 1874 ierr = DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer);CHKERRQ(ierr); 1875 } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1876 ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1877 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1878 PetscFunctionReturn(0); 1879 #else 1880 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1881 #endif 1882 } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 1883 } 1884 1885 /*@ 1886 DMPlexTopologyLoad - Loads a topology into a DMPlex 1887 1888 Collective on DM 1889 1890 Input Parameters: 1891 + dm - The DM into which the topology is loaded 1892 - viewer - The PetscViewer for the saved topology 1893 1894 Output Parameters: 1895 . 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 1896 1897 Level: advanced 1898 1899 .seealso: DMLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1900 @*/ 1901 PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 1902 { 1903 PetscBool ishdf5; 1904 PetscErrorCode ierr; 1905 1906 PetscFunctionBegin; 1907 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1908 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1909 if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 1910 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1911 if (ishdf5) { 1912 #if defined(PETSC_HAVE_HDF5) 1913 PetscViewerFormat format; 1914 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1915 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1916 ierr = DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 1917 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1918 #else 1919 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1920 #endif 1921 } 1922 PetscFunctionReturn(0); 1923 } 1924 1925 /*@ 1926 DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 1927 1928 Collective on DM 1929 1930 Input Parameters: 1931 + dm - The DM into which the coordinates are loaded 1932 - viewer - The PetscViewer for the saved coordinates 1933 1934 Level: advanced 1935 1936 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1937 @*/ 1938 PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer) 1939 { 1940 PetscBool ishdf5; 1941 PetscErrorCode ierr; 1942 1943 PetscFunctionBegin; 1944 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1945 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1946 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1947 if (ishdf5) { 1948 #if defined(PETSC_HAVE_HDF5) 1949 PetscViewerFormat format; 1950 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1951 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1952 ierr = DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1953 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1954 #else 1955 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1956 #endif 1957 } 1958 PetscFunctionReturn(0); 1959 } 1960 1961 /*@ 1962 DMPlexLabelsLoad - Loads labels into a DMPlex 1963 1964 Collective on DM 1965 1966 Input Parameters: 1967 + dm - The DM into which the labels are loaded 1968 - viewer - The PetscViewer for the saved labels 1969 1970 Level: advanced 1971 1972 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1973 @*/ 1974 PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer) 1975 { 1976 PetscBool ishdf5; 1977 PetscErrorCode ierr; 1978 1979 PetscFunctionBegin; 1980 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1981 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1982 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1983 if (ishdf5) { 1984 #if defined(PETSC_HAVE_HDF5) 1985 PetscViewerFormat format; 1986 1987 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1988 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1989 ierr = DMPlexLabelsLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1990 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1991 #else 1992 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1993 #endif 1994 } 1995 PetscFunctionReturn(0); 1996 } 1997 1998 /*@ 1999 DMPlexSectionLoad - Loads section into a DMPlex 2000 2001 Collective on DM 2002 2003 Input Parameters: 2004 + dm - The DM that represents the topology 2005 . viewer - The PetscViewer that represents the on-disk section (sectionA) 2006 . sectiondm - The DM into which the on-disk section (sectionA) is migrated 2007 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2008 2009 Output Parameters 2010 + 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) 2011 - 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) 2012 2013 Level: advanced 2014 2015 Notes: 2016 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. 2017 2018 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. 2019 2020 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. 2021 2022 Example using 2 processes: 2023 $ NX (number of points on dm): 4 2024 $ sectionA : the on-disk section 2025 $ vecA : a vector associated with sectionA 2026 $ sectionB : sectiondm's local section constructed in this function 2027 $ vecB (local) : a vector associated with sectiondm's local section 2028 $ vecB (global) : a vector associated with sectiondm's global section 2029 $ 2030 $ rank 0 rank 1 2031 $ vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2032 $ sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2033 $ sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2034 $ sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2035 $ [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2036 $ sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2037 $ sectionB->atlasDof : 1 0 1 | 1 3 2038 $ sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2039 $ vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2040 $ vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2041 $ 2042 $ where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2043 2044 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad(), PetscSectionLoad(), DMPlexSectionView() 2045 @*/ 2046 PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2047 { 2048 PetscBool ishdf5; 2049 PetscErrorCode ierr; 2050 2051 PetscFunctionBegin; 2052 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2053 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2054 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2055 PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 2056 if (globalDofSF) PetscValidPointer(globalDofSF, 5); 2057 if (localDofSF) PetscValidPointer(localDofSF, 6); 2058 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2059 if (ishdf5) { 2060 #if defined(PETSC_HAVE_HDF5) 2061 ierr = DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF);CHKERRQ(ierr); 2062 #else 2063 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2064 #endif 2065 } 2066 PetscFunctionReturn(0); 2067 } 2068 2069 /*@ 2070 DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 2071 2072 Collective on DM 2073 2074 Input Parameters: 2075 + dm - The DM that represents the topology 2076 . viewer - The PetscViewer that represents the on-disk vector data 2077 . sectiondm - The DM that contains the global section on which vec is defined 2078 . sf - The SF that migrates the on-disk vector data into vec 2079 - vec - The global vector to set values of 2080 2081 Level: advanced 2082 2083 Notes: 2084 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. 2085 2086 Typical calling sequence 2087 $ DMCreate(PETSC_COMM_WORLD, &dm); 2088 $ DMSetType(dm, DMPLEX); 2089 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2090 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2091 $ DMClone(dm, §iondm); 2092 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2093 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2094 $ DMGetGlobalVector(sectiondm, &vec); 2095 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2096 $ DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2097 $ DMRestoreGlobalVector(sectiondm, &vec); 2098 $ PetscSFDestroy(&gsf); 2099 $ PetscSFDestroy(&sfX); 2100 $ DMDestroy(§iondm); 2101 $ DMDestroy(&dm); 2102 2103 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexLocalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2104 @*/ 2105 PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2106 { 2107 PetscBool ishdf5; 2108 PetscErrorCode ierr; 2109 2110 PetscFunctionBegin; 2111 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2112 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2113 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2114 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2115 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2116 /* Check consistency */ 2117 { 2118 PetscSection section; 2119 PetscBool includesConstraints; 2120 PetscInt m, m1; 2121 2122 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2123 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 2124 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2125 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2126 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2127 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 2128 } 2129 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2130 if (ishdf5) { 2131 #if defined(PETSC_HAVE_HDF5) 2132 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2133 #else 2134 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2135 #endif 2136 } 2137 PetscFunctionReturn(0); 2138 } 2139 2140 /*@ 2141 DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 2142 2143 Collective on DM 2144 2145 Input Parameters: 2146 + dm - The DM that represents the topology 2147 . viewer - The PetscViewer that represents the on-disk vector data 2148 . sectiondm - The DM that contains the local section on which vec is defined 2149 . sf - The SF that migrates the on-disk vector data into vec 2150 - vec - The local vector to set values of 2151 2152 Level: advanced 2153 2154 Notes: 2155 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. 2156 2157 Typical calling sequence 2158 $ DMCreate(PETSC_COMM_WORLD, &dm); 2159 $ DMSetType(dm, DMPLEX); 2160 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2161 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2162 $ DMClone(dm, §iondm); 2163 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2164 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2165 $ DMGetLocalVector(sectiondm, &vec); 2166 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2167 $ DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2168 $ DMRestoreLocalVector(sectiondm, &vec); 2169 $ PetscSFDestroy(&lsf); 2170 $ PetscSFDestroy(&sfX); 2171 $ DMDestroy(§iondm); 2172 $ DMDestroy(&dm); 2173 2174 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexGlobalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2175 @*/ 2176 PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2177 { 2178 PetscBool ishdf5; 2179 PetscErrorCode ierr; 2180 2181 PetscFunctionBegin; 2182 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2183 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2184 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2185 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2186 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2187 /* Check consistency */ 2188 { 2189 PetscSection section; 2190 PetscBool includesConstraints; 2191 PetscInt m, m1; 2192 2193 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2194 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 2195 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2196 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2197 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2198 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 2199 } 2200 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2201 if (ishdf5) { 2202 #if defined(PETSC_HAVE_HDF5) 2203 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2204 #else 2205 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2206 #endif 2207 } 2208 PetscFunctionReturn(0); 2209 } 2210 2211 PetscErrorCode DMDestroy_Plex(DM dm) 2212 { 2213 DM_Plex *mesh = (DM_Plex*) dm->data; 2214 PetscErrorCode ierr; 2215 2216 PetscFunctionBegin; 2217 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr); 2218 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr); 2219 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL);CHKERRQ(ierr); 2220 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL);CHKERRQ(ierr); 2221 if (--mesh->refct > 0) PetscFunctionReturn(0); 2222 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 2223 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 2224 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 2225 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 2226 ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr); 2227 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 2228 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 2229 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 2230 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 2231 ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 2232 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 2233 ierr = ISDestroy(&mesh->subpointIS);CHKERRQ(ierr); 2234 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 2235 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 2236 ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 2237 ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 2238 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 2239 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 2240 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 2241 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 2242 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 2243 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 2244 ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr); 2245 ierr = PetscFree(mesh->neighbors);CHKERRQ(ierr); 2246 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 2247 ierr = PetscFree(mesh);CHKERRQ(ierr); 2248 PetscFunctionReturn(0); 2249 } 2250 2251 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2252 { 2253 PetscSection sectionGlobal; 2254 PetscInt bs = -1, mbs; 2255 PetscInt localSize; 2256 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2257 PetscErrorCode ierr; 2258 MatType mtype; 2259 ISLocalToGlobalMapping ltog; 2260 2261 PetscFunctionBegin; 2262 ierr = MatInitializePackage();CHKERRQ(ierr); 2263 mtype = dm->mattype; 2264 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 2265 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 2266 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 2267 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 2268 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 2269 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 2270 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 2271 ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr); 2272 if (mbs > 1) bs = mbs; 2273 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 2274 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 2275 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 2276 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 2277 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 2278 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 2279 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 2280 ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr); 2281 if (!isShell) { 2282 PetscSection subSection; 2283 PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 2284 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *ltogidx, lsize; 2285 PetscInt pStart, pEnd, p, dof, cdof; 2286 2287 /* Set localtoglobalmapping on the matrix for MatSetValuesLocal() to work (it also creates the local matrices in case of MATIS) */ 2288 if (isMatIS) { /* need a different l2g map than the one computed by DMGetLocalToGlobalMapping */ 2289 PetscSection section; 2290 PetscInt size; 2291 2292 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 2293 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 2294 ierr = PetscMalloc1(size,<ogidx);CHKERRQ(ierr); 2295 ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr); 2296 } else { 2297 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 2298 } 2299 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 2300 for (p = pStart, lsize = 0; p < pEnd; ++p) { 2301 PetscInt bdof; 2302 2303 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 2304 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 2305 dof = dof < 0 ? -(dof+1) : dof; 2306 bdof = cdof && (dof-cdof) ? 1 : dof; 2307 if (dof) { 2308 if (bs < 0) {bs = bdof;} 2309 else if (bs != bdof) {bs = 1; if (!isMatIS) break;} 2310 } 2311 if (isMatIS) { 2312 PetscInt loff,c,off; 2313 ierr = PetscSectionGetOffset(subSection, p, &loff);CHKERRQ(ierr); 2314 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 2315 for (c = 0; c < dof-cdof; ++c, ++lsize) ltogidx[loff+c] = off > -1 ? off+c : -(off+1)+c; 2316 } 2317 } 2318 /* Must have same blocksize on all procs (some might have no points) */ 2319 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 2320 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 2321 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 2322 else {bs = bsMinMax[0];} 2323 bs = PetscMax(1,bs); 2324 if (isMatIS) { /* Must reduce indices by blocksize */ 2325 PetscInt l; 2326 2327 lsize = lsize/bs; 2328 if (bs > 1) for (l = 0; l < lsize; ++l) ltogidx[l] = ltogidx[l*bs]/bs; 2329 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, lsize, ltogidx, PETSC_OWN_POINTER, <og);CHKERRQ(ierr); 2330 } 2331 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 2332 if (isMatIS) { 2333 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 2334 } 2335 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 2336 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 2337 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 2338 } 2339 ierr = MatSetDM(*J, dm);CHKERRQ(ierr); 2340 PetscFunctionReturn(0); 2341 } 2342 2343 /*@ 2344 DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2345 2346 Not collective 2347 2348 Input Parameter: 2349 . mesh - The DMPlex 2350 2351 Output Parameters: 2352 . subsection - The subdomain section 2353 2354 Level: developer 2355 2356 .seealso: 2357 @*/ 2358 PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2359 { 2360 DM_Plex *mesh = (DM_Plex*) dm->data; 2361 PetscErrorCode ierr; 2362 2363 PetscFunctionBegin; 2364 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2365 if (!mesh->subdomainSection) { 2366 PetscSection section; 2367 PetscSF sf; 2368 2369 ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr); 2370 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 2371 ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr); 2372 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 2373 } 2374 *subsection = mesh->subdomainSection; 2375 PetscFunctionReturn(0); 2376 } 2377 2378 /*@ 2379 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2380 2381 Not collective 2382 2383 Input Parameter: 2384 . mesh - The DMPlex 2385 2386 Output Parameters: 2387 + pStart - The first mesh point 2388 - pEnd - The upper bound for mesh points 2389 2390 Level: beginner 2391 2392 .seealso: DMPlexCreate(), DMPlexSetChart() 2393 @*/ 2394 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2395 { 2396 DM_Plex *mesh = (DM_Plex*) dm->data; 2397 PetscErrorCode ierr; 2398 2399 PetscFunctionBegin; 2400 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2401 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2402 PetscFunctionReturn(0); 2403 } 2404 2405 /*@ 2406 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2407 2408 Not collective 2409 2410 Input Parameters: 2411 + mesh - The DMPlex 2412 . pStart - The first mesh point 2413 - pEnd - The upper bound for mesh points 2414 2415 Output Parameters: 2416 2417 Level: beginner 2418 2419 .seealso: DMPlexCreate(), DMPlexGetChart() 2420 @*/ 2421 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2422 { 2423 DM_Plex *mesh = (DM_Plex*) dm->data; 2424 PetscErrorCode ierr; 2425 2426 PetscFunctionBegin; 2427 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2428 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2429 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 2430 PetscFunctionReturn(0); 2431 } 2432 2433 /*@ 2434 DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2435 2436 Not collective 2437 2438 Input Parameters: 2439 + mesh - The DMPlex 2440 - p - The point, which must lie in the chart set with DMPlexSetChart() 2441 2442 Output Parameter: 2443 . size - The cone size for point p 2444 2445 Level: beginner 2446 2447 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2448 @*/ 2449 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2450 { 2451 DM_Plex *mesh = (DM_Plex*) dm->data; 2452 PetscErrorCode ierr; 2453 2454 PetscFunctionBegin; 2455 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2456 PetscValidPointer(size, 3); 2457 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2458 PetscFunctionReturn(0); 2459 } 2460 2461 /*@ 2462 DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2463 2464 Not collective 2465 2466 Input Parameters: 2467 + mesh - The DMPlex 2468 . p - The point, which must lie in the chart set with DMPlexSetChart() 2469 - size - The cone size for point p 2470 2471 Output Parameter: 2472 2473 Note: 2474 This should be called after DMPlexSetChart(). 2475 2476 Level: beginner 2477 2478 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 2479 @*/ 2480 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2481 { 2482 DM_Plex *mesh = (DM_Plex*) dm->data; 2483 PetscErrorCode ierr; 2484 2485 PetscFunctionBegin; 2486 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2487 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2488 2489 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 2490 PetscFunctionReturn(0); 2491 } 2492 2493 /*@ 2494 DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2495 2496 Not collective 2497 2498 Input Parameters: 2499 + mesh - The DMPlex 2500 . p - The point, which must lie in the chart set with DMPlexSetChart() 2501 - size - The additional cone size for point p 2502 2503 Output Parameter: 2504 2505 Note: 2506 This should be called after DMPlexSetChart(). 2507 2508 Level: beginner 2509 2510 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 2511 @*/ 2512 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2513 { 2514 DM_Plex *mesh = (DM_Plex*) dm->data; 2515 PetscInt csize; 2516 PetscErrorCode ierr; 2517 2518 PetscFunctionBegin; 2519 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2520 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2521 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 2522 2523 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 2524 PetscFunctionReturn(0); 2525 } 2526 2527 /*@C 2528 DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2529 2530 Not collective 2531 2532 Input Parameters: 2533 + dm - The DMPlex 2534 - p - The point, which must lie in the chart set with DMPlexSetChart() 2535 2536 Output Parameter: 2537 . cone - An array of points which are on the in-edges for point p 2538 2539 Level: beginner 2540 2541 Fortran Notes: 2542 Since it returns an array, this routine is only available in Fortran 90, and you must 2543 include petsc.h90 in your code. 2544 You must also call DMPlexRestoreCone() after you finish using the returned array. 2545 DMPlexRestoreCone() is not needed/available in C. 2546 2547 .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart() 2548 @*/ 2549 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2550 { 2551 DM_Plex *mesh = (DM_Plex*) dm->data; 2552 PetscInt off; 2553 PetscErrorCode ierr; 2554 2555 PetscFunctionBegin; 2556 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2557 PetscValidPointer(cone, 3); 2558 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2559 *cone = &mesh->cones[off]; 2560 PetscFunctionReturn(0); 2561 } 2562 2563 /*@C 2564 DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 2565 2566 Not collective 2567 2568 Input Parameters: 2569 + dm - The DMPlex 2570 - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 2571 2572 Output Parameter: 2573 + pConesSection - PetscSection describing the layout of pCones 2574 - pCones - An array of points which are on the in-edges for the point set p 2575 2576 Level: intermediate 2577 2578 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart() 2579 @*/ 2580 PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 2581 { 2582 PetscSection cs, newcs; 2583 PetscInt *cones; 2584 PetscInt *newarr=NULL; 2585 PetscInt n; 2586 PetscErrorCode ierr; 2587 2588 PetscFunctionBegin; 2589 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 2590 ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr); 2591 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 2592 if (pConesSection) *pConesSection = newcs; 2593 if (pCones) { 2594 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 2595 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr); 2596 } 2597 PetscFunctionReturn(0); 2598 } 2599 2600 /*@ 2601 DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2602 2603 Not collective 2604 2605 Input Parameters: 2606 + dm - The DMPlex 2607 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2608 2609 Output Parameter: 2610 . expandedPoints - An array of vertices recursively expanded from input points 2611 2612 Level: advanced 2613 2614 Notes: 2615 Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2616 There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2617 2618 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth() 2619 @*/ 2620 PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2621 { 2622 IS *expandedPointsAll; 2623 PetscInt depth; 2624 PetscErrorCode ierr; 2625 2626 PetscFunctionBegin; 2627 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2628 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2629 PetscValidPointer(expandedPoints, 3); 2630 ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2631 *expandedPoints = expandedPointsAll[0]; 2632 ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]);CHKERRQ(ierr); 2633 ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2634 PetscFunctionReturn(0); 2635 } 2636 2637 /*@ 2638 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). 2639 2640 Not collective 2641 2642 Input Parameters: 2643 + dm - The DMPlex 2644 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2645 2646 Output Parameter: 2647 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2648 . expandedPoints - (optional) An array of index sets with recursively expanded cones 2649 - sections - (optional) An array of sections which describe mappings from points to their cone points 2650 2651 Level: advanced 2652 2653 Notes: 2654 Like DMPlexGetConeTuple() but recursive. 2655 2656 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. 2657 For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2658 2659 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: 2660 (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2661 (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2662 2663 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2664 @*/ 2665 PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2666 { 2667 const PetscInt *arr0=NULL, *cone=NULL; 2668 PetscInt *arr=NULL, *newarr=NULL; 2669 PetscInt d, depth_, i, n, newn, cn, co, start, end; 2670 IS *expandedPoints_; 2671 PetscSection *sections_; 2672 PetscErrorCode ierr; 2673 2674 PetscFunctionBegin; 2675 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2676 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2677 if (depth) PetscValidIntPointer(depth, 3); 2678 if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2679 if (sections) PetscValidPointer(sections, 5); 2680 ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr); 2681 ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr); 2682 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2683 ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr); 2684 ierr = PetscCalloc1(depth_, §ions_);CHKERRQ(ierr); 2685 arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2686 for (d=depth_-1; d>=0; d--) { 2687 ierr = PetscSectionCreate(PETSC_COMM_SELF, §ions_[d]);CHKERRQ(ierr); 2688 ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr); 2689 for (i=0; i<n; i++) { 2690 ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr); 2691 if (arr[i] >= start && arr[i] < end) { 2692 ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr); 2693 ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr); 2694 } else { 2695 ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr); 2696 } 2697 } 2698 ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr); 2699 ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr); 2700 ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr); 2701 for (i=0; i<n; i++) { 2702 ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr); 2703 ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr); 2704 if (cn > 1) { 2705 ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr); 2706 ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr); 2707 } else { 2708 newarr[co] = arr[i]; 2709 } 2710 } 2711 ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr); 2712 arr = newarr; 2713 n = newn; 2714 } 2715 ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr); 2716 *depth = depth_; 2717 if (expandedPoints) *expandedPoints = expandedPoints_; 2718 else { 2719 for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);} 2720 ierr = PetscFree(expandedPoints_);CHKERRQ(ierr); 2721 } 2722 if (sections) *sections = sections_; 2723 else { 2724 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(§ions_[d]);CHKERRQ(ierr);} 2725 ierr = PetscFree(sections_);CHKERRQ(ierr); 2726 } 2727 PetscFunctionReturn(0); 2728 } 2729 2730 /*@ 2731 DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2732 2733 Not collective 2734 2735 Input Parameters: 2736 + dm - The DMPlex 2737 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2738 2739 Output Parameter: 2740 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2741 . expandedPoints - (optional) An array of recursively expanded cones 2742 - sections - (optional) An array of sections which describe mappings from points to their cone points 2743 2744 Level: advanced 2745 2746 Notes: 2747 See DMPlexGetConeRecursive() for details. 2748 2749 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2750 @*/ 2751 PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2752 { 2753 PetscInt d, depth_; 2754 PetscErrorCode ierr; 2755 2756 PetscFunctionBegin; 2757 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2758 if (depth && *depth != depth_) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2759 if (depth) *depth = 0; 2760 if (expandedPoints) { 2761 for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);} 2762 ierr = PetscFree(*expandedPoints);CHKERRQ(ierr); 2763 } 2764 if (sections) { 2765 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);} 2766 ierr = PetscFree(*sections);CHKERRQ(ierr); 2767 } 2768 PetscFunctionReturn(0); 2769 } 2770 2771 /*@ 2772 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 2773 2774 Not collective 2775 2776 Input Parameters: 2777 + mesh - The DMPlex 2778 . p - The point, which must lie in the chart set with DMPlexSetChart() 2779 - cone - An array of points which are on the in-edges for point p 2780 2781 Output Parameter: 2782 2783 Note: 2784 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2785 2786 Level: beginner 2787 2788 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize() 2789 @*/ 2790 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 2791 { 2792 DM_Plex *mesh = (DM_Plex*) dm->data; 2793 PetscInt pStart, pEnd; 2794 PetscInt dof, off, c; 2795 PetscErrorCode ierr; 2796 2797 PetscFunctionBegin; 2798 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2799 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2800 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2801 if (dof) PetscValidPointer(cone, 3); 2802 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2803 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 2804 for (c = 0; c < dof; ++c) { 2805 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 2806 mesh->cones[off+c] = cone[c]; 2807 } 2808 PetscFunctionReturn(0); 2809 } 2810 2811 /*@C 2812 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 2813 2814 Not collective 2815 2816 Input Parameters: 2817 + mesh - The DMPlex 2818 - p - The point, which must lie in the chart set with DMPlexSetChart() 2819 2820 Output Parameter: 2821 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2822 integer giving the prescription for cone traversal. If it is negative, the cone is 2823 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 2824 the index of the cone point on which to start. 2825 2826 Level: beginner 2827 2828 Fortran Notes: 2829 Since it returns an array, this routine is only available in Fortran 90, and you must 2830 include petsc.h90 in your code. 2831 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 2832 DMPlexRestoreConeOrientation() is not needed/available in C. 2833 2834 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 2835 @*/ 2836 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 2837 { 2838 DM_Plex *mesh = (DM_Plex*) dm->data; 2839 PetscInt off; 2840 PetscErrorCode ierr; 2841 2842 PetscFunctionBegin; 2843 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2844 if (PetscDefined(USE_DEBUG)) { 2845 PetscInt dof; 2846 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2847 if (dof) PetscValidPointer(coneOrientation, 3); 2848 } 2849 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2850 2851 *coneOrientation = &mesh->coneOrientations[off]; 2852 PetscFunctionReturn(0); 2853 } 2854 2855 /*@ 2856 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 2857 2858 Not collective 2859 2860 Input Parameters: 2861 + mesh - The DMPlex 2862 . p - The point, which must lie in the chart set with DMPlexSetChart() 2863 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2864 integer giving the prescription for cone traversal. If it is negative, the cone is 2865 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 2866 the index of the cone point on which to start. 2867 2868 Output Parameter: 2869 2870 Note: 2871 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2872 2873 Level: beginner 2874 2875 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2876 @*/ 2877 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 2878 { 2879 DM_Plex *mesh = (DM_Plex*) dm->data; 2880 PetscInt pStart, pEnd; 2881 PetscInt dof, off, c; 2882 PetscErrorCode ierr; 2883 2884 PetscFunctionBegin; 2885 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2886 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2887 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2888 if (dof) PetscValidPointer(coneOrientation, 3); 2889 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2890 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 2891 for (c = 0; c < dof; ++c) { 2892 PetscInt cdof, o = coneOrientation[c]; 2893 2894 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 2895 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 2896 mesh->coneOrientations[off+c] = o; 2897 } 2898 PetscFunctionReturn(0); 2899 } 2900 2901 /*@ 2902 DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 2903 2904 Not collective 2905 2906 Input Parameters: 2907 + mesh - The DMPlex 2908 . p - The point, which must lie in the chart set with DMPlexSetChart() 2909 . conePos - The local index in the cone where the point should be put 2910 - conePoint - The mesh point to insert 2911 2912 Level: beginner 2913 2914 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2915 @*/ 2916 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 2917 { 2918 DM_Plex *mesh = (DM_Plex*) dm->data; 2919 PetscInt pStart, pEnd; 2920 PetscInt dof, off; 2921 PetscErrorCode ierr; 2922 2923 PetscFunctionBegin; 2924 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2925 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2926 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 2927 if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 2928 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2929 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2930 if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 2931 mesh->cones[off+conePos] = conePoint; 2932 PetscFunctionReturn(0); 2933 } 2934 2935 /*@ 2936 DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 2937 2938 Not collective 2939 2940 Input Parameters: 2941 + mesh - The DMPlex 2942 . p - The point, which must lie in the chart set with DMPlexSetChart() 2943 . conePos - The local index in the cone where the point should be put 2944 - coneOrientation - The point orientation to insert 2945 2946 Level: beginner 2947 2948 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2949 @*/ 2950 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 2951 { 2952 DM_Plex *mesh = (DM_Plex*) dm->data; 2953 PetscInt pStart, pEnd; 2954 PetscInt dof, off; 2955 PetscErrorCode ierr; 2956 2957 PetscFunctionBegin; 2958 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2959 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2960 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 2961 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2962 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2963 if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 2964 mesh->coneOrientations[off+conePos] = coneOrientation; 2965 PetscFunctionReturn(0); 2966 } 2967 2968 /*@ 2969 DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 2970 2971 Not collective 2972 2973 Input Parameters: 2974 + mesh - The DMPlex 2975 - p - The point, which must lie in the chart set with DMPlexSetChart() 2976 2977 Output Parameter: 2978 . size - The support size for point p 2979 2980 Level: beginner 2981 2982 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 2983 @*/ 2984 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 2985 { 2986 DM_Plex *mesh = (DM_Plex*) dm->data; 2987 PetscErrorCode ierr; 2988 2989 PetscFunctionBegin; 2990 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2991 PetscValidPointer(size, 3); 2992 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 2993 PetscFunctionReturn(0); 2994 } 2995 2996 /*@ 2997 DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 2998 2999 Not collective 3000 3001 Input Parameters: 3002 + mesh - The DMPlex 3003 . p - The point, which must lie in the chart set with DMPlexSetChart() 3004 - size - The support size for point p 3005 3006 Output Parameter: 3007 3008 Note: 3009 This should be called after DMPlexSetChart(). 3010 3011 Level: beginner 3012 3013 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 3014 @*/ 3015 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3016 { 3017 DM_Plex *mesh = (DM_Plex*) dm->data; 3018 PetscErrorCode ierr; 3019 3020 PetscFunctionBegin; 3021 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3022 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3023 3024 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 3025 PetscFunctionReturn(0); 3026 } 3027 3028 /*@C 3029 DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3030 3031 Not collective 3032 3033 Input Parameters: 3034 + mesh - The DMPlex 3035 - p - The point, which must lie in the chart set with DMPlexSetChart() 3036 3037 Output Parameter: 3038 . support - An array of points which are on the out-edges for point p 3039 3040 Level: beginner 3041 3042 Fortran Notes: 3043 Since it returns an array, this routine is only available in Fortran 90, and you must 3044 include petsc.h90 in your code. 3045 You must also call DMPlexRestoreSupport() after you finish using the returned array. 3046 DMPlexRestoreSupport() is not needed/available in C. 3047 3048 .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart() 3049 @*/ 3050 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3051 { 3052 DM_Plex *mesh = (DM_Plex*) dm->data; 3053 PetscInt off; 3054 PetscErrorCode ierr; 3055 3056 PetscFunctionBegin; 3057 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3058 PetscValidPointer(support, 3); 3059 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3060 *support = &mesh->supports[off]; 3061 PetscFunctionReturn(0); 3062 } 3063 3064 /*@ 3065 DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 3066 3067 Not collective 3068 3069 Input Parameters: 3070 + mesh - The DMPlex 3071 . p - The point, which must lie in the chart set with DMPlexSetChart() 3072 - support - An array of points which are on the out-edges for point p 3073 3074 Output Parameter: 3075 3076 Note: 3077 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 3078 3079 Level: beginner 3080 3081 .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 3082 @*/ 3083 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3084 { 3085 DM_Plex *mesh = (DM_Plex*) dm->data; 3086 PetscInt pStart, pEnd; 3087 PetscInt dof, off, c; 3088 PetscErrorCode ierr; 3089 3090 PetscFunctionBegin; 3091 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3092 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3093 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3094 if (dof) PetscValidPointer(support, 3); 3095 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3096 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 3097 for (c = 0; c < dof; ++c) { 3098 if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 3099 mesh->supports[off+c] = support[c]; 3100 } 3101 PetscFunctionReturn(0); 3102 } 3103 3104 /*@ 3105 DMPlexInsertSupport - Insert a point into the out-edges for the point p 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 . supportPos - The local index in the cone where the point should be put 3113 - supportPoint - The mesh point to insert 3114 3115 Level: beginner 3116 3117 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3118 @*/ 3119 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3120 { 3121 DM_Plex *mesh = (DM_Plex*) dm->data; 3122 PetscInt pStart, pEnd; 3123 PetscInt dof, off; 3124 PetscErrorCode ierr; 3125 3126 PetscFunctionBegin; 3127 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3128 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3129 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3130 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3131 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 3132 if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 3133 if (supportPos >= dof) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 3134 mesh->supports[off+supportPos] = supportPoint; 3135 PetscFunctionReturn(0); 3136 } 3137 3138 /*@C 3139 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3140 3141 Not collective 3142 3143 Input Parameters: 3144 + mesh - The DMPlex 3145 . p - The point, which must lie in the chart set with DMPlexSetChart() 3146 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 3147 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 3148 3149 Output Parameters: 3150 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3151 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3152 3153 Note: 3154 If using internal storage (points is NULL on input), each call overwrites the last output. 3155 3156 Fortran Notes: 3157 Since it returns an array, this routine is only available in Fortran 90, and you must 3158 include petsc.h90 in your code. 3159 3160 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3161 3162 Level: beginner 3163 3164 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3165 @*/ 3166 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3167 { 3168 DM_Plex *mesh = (DM_Plex*) dm->data; 3169 PetscInt *closure, *fifo; 3170 const PetscInt *tmp = NULL, *tmpO = NULL; 3171 PetscInt tmpSize, t; 3172 PetscInt depth = 0, maxSize; 3173 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 3174 PetscErrorCode ierr; 3175 3176 PetscFunctionBegin; 3177 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3178 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3179 /* This is only 1-level */ 3180 if (useCone) { 3181 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 3182 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 3183 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 3184 } else { 3185 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 3186 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 3187 } 3188 if (depth == 1) { 3189 if (*points) { 3190 closure = *points; 3191 } else { 3192 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 3193 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 3194 } 3195 closure[0] = p; closure[1] = 0; 3196 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 3197 closure[closureSize] = tmp[t]; 3198 closure[closureSize+1] = tmpO ? tmpO[t] : 0; 3199 } 3200 if (numPoints) *numPoints = closureSize/2; 3201 if (points) *points = closure; 3202 PetscFunctionReturn(0); 3203 } 3204 { 3205 PetscInt c, coneSeries, s,supportSeries; 3206 3207 c = mesh->maxConeSize; 3208 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 3209 s = mesh->maxSupportSize; 3210 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 3211 maxSize = 2*PetscMax(coneSeries,supportSeries); 3212 } 3213 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3214 if (*points) { 3215 closure = *points; 3216 } else { 3217 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 3218 } 3219 closure[0] = p; closure[1] = 0; 3220 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 3221 const PetscInt cp = tmp[t]; 3222 const PetscInt co = tmpO ? tmpO[t] : 0; 3223 3224 closure[closureSize] = cp; 3225 closure[closureSize+1] = co; 3226 fifo[fifoSize] = cp; 3227 fifo[fifoSize+1] = co; 3228 } 3229 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3230 while (fifoSize - fifoStart) { 3231 const PetscInt q = fifo[fifoStart]; 3232 const PetscInt o = fifo[fifoStart+1]; 3233 const PetscInt rev = o >= 0 ? 0 : 1; 3234 const PetscInt off = rev ? -(o+1) : o; 3235 3236 if (useCone) { 3237 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 3238 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 3239 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 3240 } else { 3241 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 3242 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 3243 tmpO = NULL; 3244 } 3245 for (t = 0; t < tmpSize; ++t) { 3246 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 3247 const PetscInt cp = tmp[i]; 3248 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 3249 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 3250 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 3251 PetscInt co = tmpO ? tmpO[i] : 0; 3252 PetscInt c; 3253 3254 if (rev) { 3255 PetscInt childSize, coff; 3256 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 3257 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 3258 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 3259 } 3260 /* Check for duplicate */ 3261 for (c = 0; c < closureSize; c += 2) { 3262 if (closure[c] == cp) break; 3263 } 3264 if (c == closureSize) { 3265 closure[closureSize] = cp; 3266 closure[closureSize+1] = co; 3267 fifo[fifoSize] = cp; 3268 fifo[fifoSize+1] = co; 3269 closureSize += 2; 3270 fifoSize += 2; 3271 } 3272 } 3273 fifoStart += 2; 3274 } 3275 if (numPoints) *numPoints = closureSize/2; 3276 if (points) *points = closure; 3277 ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3278 PetscFunctionReturn(0); 3279 } 3280 3281 /*@C 3282 DMPlexGetTransitiveClosure_Internal - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG with a specified initial orientation 3283 3284 Not collective 3285 3286 Input Parameters: 3287 + mesh - The DMPlex 3288 . p - The point, which must lie in the chart set with DMPlexSetChart() 3289 . orientation - The orientation of the point 3290 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 3291 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 3292 3293 Output Parameters: 3294 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3295 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3296 3297 Note: 3298 If using internal storage (points is NULL on input), each call overwrites the last output. 3299 3300 Fortran Notes: 3301 Since it returns an array, this routine is only available in Fortran 90, and you must 3302 include petsc.h90 in your code. 3303 3304 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3305 3306 Level: beginner 3307 3308 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3309 @*/ 3310 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3311 { 3312 DM_Plex *mesh = (DM_Plex*) dm->data; 3313 PetscInt *closure, *fifo; 3314 const PetscInt *tmp = NULL, *tmpO = NULL; 3315 PetscInt tmpSize, t; 3316 PetscInt depth = 0, maxSize; 3317 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 3318 PetscErrorCode ierr; 3319 3320 PetscFunctionBegin; 3321 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3322 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3323 /* This is only 1-level */ 3324 if (useCone) { 3325 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 3326 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 3327 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 3328 } else { 3329 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 3330 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 3331 } 3332 if (depth == 1) { 3333 if (*points) { 3334 closure = *points; 3335 } else { 3336 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 3337 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 3338 } 3339 closure[0] = p; closure[1] = ornt; 3340 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 3341 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 3342 closure[closureSize] = tmp[i]; 3343 closure[closureSize+1] = tmpO ? tmpO[i] : 0; 3344 } 3345 if (numPoints) *numPoints = closureSize/2; 3346 if (points) *points = closure; 3347 PetscFunctionReturn(0); 3348 } 3349 { 3350 PetscInt c, coneSeries, s,supportSeries; 3351 3352 c = mesh->maxConeSize; 3353 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 3354 s = mesh->maxSupportSize; 3355 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 3356 maxSize = 2*PetscMax(coneSeries,supportSeries); 3357 } 3358 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3359 if (*points) { 3360 closure = *points; 3361 } else { 3362 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 3363 } 3364 closure[0] = p; closure[1] = ornt; 3365 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 3366 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 3367 const PetscInt cp = tmp[i]; 3368 PetscInt co = tmpO ? tmpO[i] : 0; 3369 3370 if (ornt < 0) { 3371 PetscInt childSize, coff; 3372 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 3373 coff = co < 0 ? -(tmpO[i]+1) : tmpO[i]; 3374 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 3375 } 3376 closure[closureSize] = cp; 3377 closure[closureSize+1] = co; 3378 fifo[fifoSize] = cp; 3379 fifo[fifoSize+1] = co; 3380 } 3381 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3382 while (fifoSize - fifoStart) { 3383 const PetscInt q = fifo[fifoStart]; 3384 const PetscInt o = fifo[fifoStart+1]; 3385 const PetscInt rev = o >= 0 ? 0 : 1; 3386 const PetscInt off = rev ? -(o+1) : o; 3387 3388 if (useCone) { 3389 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 3390 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 3391 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 3392 } else { 3393 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 3394 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 3395 tmpO = NULL; 3396 } 3397 for (t = 0; t < tmpSize; ++t) { 3398 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 3399 const PetscInt cp = tmp[i]; 3400 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 3401 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 3402 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 3403 PetscInt co = tmpO ? tmpO[i] : 0; 3404 PetscInt c; 3405 3406 if (rev) { 3407 PetscInt childSize, coff; 3408 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 3409 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 3410 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 3411 } 3412 /* Check for duplicate */ 3413 for (c = 0; c < closureSize; c += 2) { 3414 if (closure[c] == cp) break; 3415 } 3416 if (c == closureSize) { 3417 closure[closureSize] = cp; 3418 closure[closureSize+1] = co; 3419 fifo[fifoSize] = cp; 3420 fifo[fifoSize+1] = co; 3421 closureSize += 2; 3422 fifoSize += 2; 3423 } 3424 } 3425 fifoStart += 2; 3426 } 3427 if (numPoints) *numPoints = closureSize/2; 3428 if (points) *points = closure; 3429 ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3430 PetscFunctionReturn(0); 3431 } 3432 3433 /*@C 3434 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3435 3436 Not collective 3437 3438 Input Parameters: 3439 + mesh - The DMPlex 3440 . p - The point, which must lie in the chart set with DMPlexSetChart() 3441 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 3442 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints, zeroed on exit 3443 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...], zeroed on exit 3444 3445 Note: 3446 If not using internal storage (points is not NULL on input), this call is unnecessary 3447 3448 Fortran Notes: 3449 Since it returns an array, this routine is only available in Fortran 90, and you must 3450 include petsc.h90 in your code. 3451 3452 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3453 3454 Level: beginner 3455 3456 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3457 @*/ 3458 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3459 { 3460 PetscErrorCode ierr; 3461 3462 PetscFunctionBegin; 3463 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3464 if (numPoints) PetscValidIntPointer(numPoints,4); 3465 if (points) PetscValidPointer(points,5); 3466 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr); 3467 if (numPoints) *numPoints = 0; 3468 PetscFunctionReturn(0); 3469 } 3470 3471 /*@ 3472 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3473 3474 Not collective 3475 3476 Input Parameter: 3477 . mesh - The DMPlex 3478 3479 Output Parameters: 3480 + maxConeSize - The maximum number of in-edges 3481 - maxSupportSize - The maximum number of out-edges 3482 3483 Level: beginner 3484 3485 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 3486 @*/ 3487 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3488 { 3489 DM_Plex *mesh = (DM_Plex*) dm->data; 3490 3491 PetscFunctionBegin; 3492 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3493 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 3494 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 3495 PetscFunctionReturn(0); 3496 } 3497 3498 PetscErrorCode DMSetUp_Plex(DM dm) 3499 { 3500 DM_Plex *mesh = (DM_Plex*) dm->data; 3501 PetscInt size; 3502 PetscErrorCode ierr; 3503 3504 PetscFunctionBegin; 3505 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3506 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 3507 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 3508 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 3509 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 3510 ierr = PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt));CHKERRQ(ierr); 3511 if (mesh->maxSupportSize) { 3512 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3513 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 3514 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 3515 ierr = PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt));CHKERRQ(ierr); 3516 } 3517 PetscFunctionReturn(0); 3518 } 3519 3520 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3521 { 3522 PetscErrorCode ierr; 3523 3524 PetscFunctionBegin; 3525 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 3526 ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 3527 if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3528 if (dm->useNatural && dm->sfMigration) { 3529 PetscSF sfMigrationInv,sfNatural; 3530 PetscSection section, sectionSeq; 3531 3532 (*subdm)->sfMigration = dm->sfMigration; 3533 ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr); 3534 ierr = DMGetLocalSection((*subdm), §ion);CHKERRQ(ierr); 3535 ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3536 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq);CHKERRQ(ierr); 3537 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3538 3539 ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3540 (*subdm)->sfNatural = sfNatural; 3541 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3542 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3543 } 3544 PetscFunctionReturn(0); 3545 } 3546 3547 PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 3548 { 3549 PetscErrorCode ierr; 3550 PetscInt i = 0; 3551 3552 PetscFunctionBegin; 3553 ierr = DMClone(dms[0], superdm);CHKERRQ(ierr); 3554 ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr); 3555 (*superdm)->useNatural = PETSC_FALSE; 3556 for (i = 0; i < len; i++) { 3557 if (dms[i]->useNatural && dms[i]->sfMigration) { 3558 PetscSF sfMigrationInv,sfNatural; 3559 PetscSection section, sectionSeq; 3560 3561 (*superdm)->sfMigration = dms[i]->sfMigration; 3562 ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr); 3563 (*superdm)->useNatural = PETSC_TRUE; 3564 ierr = DMGetLocalSection((*superdm), §ion);CHKERRQ(ierr); 3565 ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3566 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq);CHKERRQ(ierr); 3567 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3568 3569 ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3570 (*superdm)->sfNatural = sfNatural; 3571 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3572 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3573 break; 3574 } 3575 } 3576 PetscFunctionReturn(0); 3577 } 3578 3579 /*@ 3580 DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3581 3582 Not collective 3583 3584 Input Parameter: 3585 . mesh - The DMPlex 3586 3587 Output Parameter: 3588 3589 Note: 3590 This should be called after all calls to DMPlexSetCone() 3591 3592 Level: beginner 3593 3594 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 3595 @*/ 3596 PetscErrorCode DMPlexSymmetrize(DM dm) 3597 { 3598 DM_Plex *mesh = (DM_Plex*) dm->data; 3599 PetscInt *offsets; 3600 PetscInt supportSize; 3601 PetscInt pStart, pEnd, p; 3602 PetscErrorCode ierr; 3603 3604 PetscFunctionBegin; 3605 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3606 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 3607 ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3608 /* Calculate support sizes */ 3609 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3610 for (p = pStart; p < pEnd; ++p) { 3611 PetscInt dof, off, c; 3612 3613 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3614 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3615 for (c = off; c < off+dof; ++c) { 3616 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 3617 } 3618 } 3619 for (p = pStart; p < pEnd; ++p) { 3620 PetscInt dof; 3621 3622 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3623 3624 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 3625 } 3626 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3627 /* Calculate supports */ 3628 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 3629 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 3630 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 3631 for (p = pStart; p < pEnd; ++p) { 3632 PetscInt dof, off, c; 3633 3634 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3635 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3636 for (c = off; c < off+dof; ++c) { 3637 const PetscInt q = mesh->cones[c]; 3638 PetscInt offS; 3639 3640 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 3641 3642 mesh->supports[offS+offsets[q]] = p; 3643 ++offsets[q]; 3644 } 3645 } 3646 ierr = PetscFree(offsets);CHKERRQ(ierr); 3647 ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3648 PetscFunctionReturn(0); 3649 } 3650 3651 static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3652 { 3653 IS stratumIS; 3654 PetscErrorCode ierr; 3655 3656 PetscFunctionBegin; 3657 if (pStart >= pEnd) PetscFunctionReturn(0); 3658 if (PetscDefined(USE_DEBUG)) { 3659 PetscInt qStart, qEnd, numLevels, level; 3660 PetscBool overlap = PETSC_FALSE; 3661 ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr); 3662 for (level = 0; level < numLevels; level++) { 3663 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3664 if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3665 } 3666 if (overlap) SETERRQ6(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); 3667 } 3668 ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr); 3669 ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr); 3670 ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 3671 PetscFunctionReturn(0); 3672 } 3673 3674 /*@ 3675 DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 3676 can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3677 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3678 the DAG. 3679 3680 Collective on dm 3681 3682 Input Parameter: 3683 . mesh - The DMPlex 3684 3685 Output Parameter: 3686 3687 Notes: 3688 Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3689 meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 3690 until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3691 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3692 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3693 3694 The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3695 if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3696 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 3697 to interpolate only that one (e0), so that 3698 $ cone(c0) = {e0, v2} 3699 $ cone(e0) = {v0, v1} 3700 If DMPlexStratify() is run on this mesh, it will give depths 3701 $ depth 0 = {v0, v1, v2} 3702 $ depth 1 = {e0, c0} 3703 where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3704 3705 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3706 3707 Level: beginner 3708 3709 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes() 3710 @*/ 3711 PetscErrorCode DMPlexStratify(DM dm) 3712 { 3713 DM_Plex *mesh = (DM_Plex*) dm->data; 3714 DMLabel label; 3715 PetscInt pStart, pEnd, p; 3716 PetscInt numRoots = 0, numLeaves = 0; 3717 PetscErrorCode ierr; 3718 3719 PetscFunctionBegin; 3720 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3721 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3722 3723 /* Create depth label */ 3724 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3725 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 3726 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3727 3728 { 3729 /* Initialize roots and count leaves */ 3730 PetscInt sMin = PETSC_MAX_INT; 3731 PetscInt sMax = PETSC_MIN_INT; 3732 PetscInt coneSize, supportSize; 3733 3734 for (p = pStart; p < pEnd; ++p) { 3735 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3736 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3737 if (!coneSize && supportSize) { 3738 sMin = PetscMin(p, sMin); 3739 sMax = PetscMax(p, sMax); 3740 ++numRoots; 3741 } else if (!supportSize && coneSize) { 3742 ++numLeaves; 3743 } else if (!supportSize && !coneSize) { 3744 /* Isolated points */ 3745 sMin = PetscMin(p, sMin); 3746 sMax = PetscMax(p, sMax); 3747 } 3748 } 3749 ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr); 3750 } 3751 3752 if (numRoots + numLeaves == (pEnd - pStart)) { 3753 PetscInt sMin = PETSC_MAX_INT; 3754 PetscInt sMax = PETSC_MIN_INT; 3755 PetscInt coneSize, supportSize; 3756 3757 for (p = pStart; p < pEnd; ++p) { 3758 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3759 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3760 if (!supportSize && coneSize) { 3761 sMin = PetscMin(p, sMin); 3762 sMax = PetscMax(p, sMax); 3763 } 3764 } 3765 ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr); 3766 } else { 3767 PetscInt level = 0; 3768 PetscInt qStart, qEnd, q; 3769 3770 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3771 while (qEnd > qStart) { 3772 PetscInt sMin = PETSC_MAX_INT; 3773 PetscInt sMax = PETSC_MIN_INT; 3774 3775 for (q = qStart; q < qEnd; ++q) { 3776 const PetscInt *support; 3777 PetscInt supportSize, s; 3778 3779 ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr); 3780 ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr); 3781 for (s = 0; s < supportSize; ++s) { 3782 sMin = PetscMin(support[s], sMin); 3783 sMax = PetscMax(support[s], sMax); 3784 } 3785 } 3786 ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr); 3787 ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr); 3788 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3789 } 3790 } 3791 { /* just in case there is an empty process */ 3792 PetscInt numValues, maxValues = 0, v; 3793 3794 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 3795 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 3796 for (v = numValues; v < maxValues; v++) { 3797 ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr); 3798 } 3799 } 3800 ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr); 3801 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3802 PetscFunctionReturn(0); 3803 } 3804 3805 PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 3806 { 3807 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3808 PetscInt dim, depth, pheight, coneSize; 3809 PetscErrorCode ierr; 3810 3811 PetscFunctionBeginHot; 3812 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3813 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3814 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3815 pheight = depth - pdepth; 3816 if (depth <= 1) { 3817 switch (pdepth) { 3818 case 0: ct = DM_POLYTOPE_POINT;break; 3819 case 1: 3820 switch (coneSize) { 3821 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3822 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3823 case 4: 3824 switch (dim) { 3825 case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 3826 case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 3827 default: break; 3828 } 3829 break; 3830 case 5: ct = DM_POLYTOPE_PYRAMID;break; 3831 case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3832 case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 3833 default: break; 3834 } 3835 } 3836 } else { 3837 if (pdepth == 0) { 3838 ct = DM_POLYTOPE_POINT; 3839 } else if (pheight == 0) { 3840 switch (dim) { 3841 case 1: 3842 switch (coneSize) { 3843 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3844 default: break; 3845 } 3846 break; 3847 case 2: 3848 switch (coneSize) { 3849 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3850 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3851 default: break; 3852 } 3853 break; 3854 case 3: 3855 switch (coneSize) { 3856 case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 3857 case 5: 3858 { 3859 const PetscInt *cone; 3860 PetscInt faceConeSize; 3861 3862 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 3863 ierr = DMPlexGetConeSize(dm, cone[0], &faceConeSize);CHKERRQ(ierr); 3864 switch (faceConeSize) { 3865 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3866 case 4: ct = DM_POLYTOPE_PYRAMID;break; 3867 } 3868 } 3869 break; 3870 case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 3871 default: break; 3872 } 3873 break; 3874 default: break; 3875 } 3876 } else if (pheight > 0) { 3877 switch (coneSize) { 3878 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3879 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3880 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3881 default: break; 3882 } 3883 } 3884 } 3885 *pt = ct; 3886 PetscFunctionReturn(0); 3887 } 3888 3889 /*@ 3890 DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 3891 3892 Collective on dm 3893 3894 Input Parameter: 3895 . mesh - The DMPlex 3896 3897 DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 3898 3899 Level: developer 3900 3901 Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 3902 internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 3903 automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 3904 3905 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel() 3906 @*/ 3907 PetscErrorCode DMPlexComputeCellTypes(DM dm) 3908 { 3909 DM_Plex *mesh; 3910 DMLabel ctLabel; 3911 PetscInt pStart, pEnd, p; 3912 PetscErrorCode ierr; 3913 3914 PetscFunctionBegin; 3915 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3916 mesh = (DM_Plex *) dm->data; 3917 ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr); 3918 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 3919 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3920 for (p = pStart; p < pEnd; ++p) { 3921 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3922 PetscInt pdepth; 3923 3924 ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr); 3925 ierr = DMPlexComputeCellType_Internal(dm, p, pdepth, &ct);CHKERRQ(ierr); 3926 if (ct == DM_POLYTOPE_UNKNOWN) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p); 3927 ierr = DMLabelSetValue(ctLabel, p, ct);CHKERRQ(ierr); 3928 } 3929 ierr = PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState);CHKERRQ(ierr); 3930 ierr = PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr); 3931 PetscFunctionReturn(0); 3932 } 3933 3934 /*@C 3935 DMPlexGetJoin - Get an array for the join of the set of points 3936 3937 Not Collective 3938 3939 Input Parameters: 3940 + dm - The DMPlex object 3941 . numPoints - The number of input points for the join 3942 - points - The input points 3943 3944 Output Parameters: 3945 + numCoveredPoints - The number of points in the join 3946 - coveredPoints - The points in the join 3947 3948 Level: intermediate 3949 3950 Note: Currently, this is restricted to a single level join 3951 3952 Fortran Notes: 3953 Since it returns an array, this routine is only available in Fortran 90, and you must 3954 include petsc.h90 in your code. 3955 3956 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3957 3958 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 3959 @*/ 3960 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3961 { 3962 DM_Plex *mesh = (DM_Plex*) dm->data; 3963 PetscInt *join[2]; 3964 PetscInt joinSize, i = 0; 3965 PetscInt dof, off, p, c, m; 3966 PetscErrorCode ierr; 3967 3968 PetscFunctionBegin; 3969 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3970 PetscValidIntPointer(points, 3); 3971 PetscValidIntPointer(numCoveredPoints, 4); 3972 PetscValidPointer(coveredPoints, 5); 3973 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 3974 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 3975 /* Copy in support of first point */ 3976 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 3977 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 3978 for (joinSize = 0; joinSize < dof; ++joinSize) { 3979 join[i][joinSize] = mesh->supports[off+joinSize]; 3980 } 3981 /* Check each successive support */ 3982 for (p = 1; p < numPoints; ++p) { 3983 PetscInt newJoinSize = 0; 3984 3985 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 3986 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 3987 for (c = 0; c < dof; ++c) { 3988 const PetscInt point = mesh->supports[off+c]; 3989 3990 for (m = 0; m < joinSize; ++m) { 3991 if (point == join[i][m]) { 3992 join[1-i][newJoinSize++] = point; 3993 break; 3994 } 3995 } 3996 } 3997 joinSize = newJoinSize; 3998 i = 1-i; 3999 } 4000 *numCoveredPoints = joinSize; 4001 *coveredPoints = join[i]; 4002 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4003 PetscFunctionReturn(0); 4004 } 4005 4006 /*@C 4007 DMPlexRestoreJoin - Restore an array for the join of the set of points 4008 4009 Not Collective 4010 4011 Input Parameters: 4012 + dm - The DMPlex object 4013 . numPoints - The number of input points for the join 4014 - points - The input points 4015 4016 Output Parameters: 4017 + numCoveredPoints - The number of points in the join 4018 - coveredPoints - The points in the join 4019 4020 Fortran Notes: 4021 Since it returns an array, this routine is only available in Fortran 90, and you must 4022 include petsc.h90 in your code. 4023 4024 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4025 4026 Level: intermediate 4027 4028 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 4029 @*/ 4030 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4031 { 4032 PetscErrorCode ierr; 4033 4034 PetscFunctionBegin; 4035 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4036 if (points) PetscValidIntPointer(points,3); 4037 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4038 PetscValidPointer(coveredPoints, 5); 4039 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4040 if (numCoveredPoints) *numCoveredPoints = 0; 4041 PetscFunctionReturn(0); 4042 } 4043 4044 /*@C 4045 DMPlexGetFullJoin - Get an array for the join of the set of points 4046 4047 Not Collective 4048 4049 Input Parameters: 4050 + dm - The DMPlex object 4051 . numPoints - The number of input points for the join 4052 - points - The input points 4053 4054 Output Parameters: 4055 + numCoveredPoints - The number of points in the join 4056 - coveredPoints - The points in the join 4057 4058 Fortran Notes: 4059 Since it returns an array, this routine is only available in Fortran 90, and you must 4060 include petsc.h90 in your code. 4061 4062 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4063 4064 Level: intermediate 4065 4066 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 4067 @*/ 4068 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4069 { 4070 DM_Plex *mesh = (DM_Plex*) dm->data; 4071 PetscInt *offsets, **closures; 4072 PetscInt *join[2]; 4073 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 4074 PetscInt p, d, c, m, ms; 4075 PetscErrorCode ierr; 4076 4077 PetscFunctionBegin; 4078 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4079 PetscValidIntPointer(points, 3); 4080 PetscValidIntPointer(numCoveredPoints, 4); 4081 PetscValidPointer(coveredPoints, 5); 4082 4083 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4084 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 4085 ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4086 ms = mesh->maxSupportSize; 4087 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 4088 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4089 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4090 4091 for (p = 0; p < numPoints; ++p) { 4092 PetscInt closureSize; 4093 4094 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 4095 4096 offsets[p*(depth+2)+0] = 0; 4097 for (d = 0; d < depth+1; ++d) { 4098 PetscInt pStart, pEnd, i; 4099 4100 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 4101 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4102 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4103 offsets[p*(depth+2)+d+1] = i; 4104 break; 4105 } 4106 } 4107 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4108 } 4109 if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 4110 } 4111 for (d = 0; d < depth+1; ++d) { 4112 PetscInt dof; 4113 4114 /* Copy in support of first point */ 4115 dof = offsets[d+1] - offsets[d]; 4116 for (joinSize = 0; joinSize < dof; ++joinSize) { 4117 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4118 } 4119 /* Check each successive cone */ 4120 for (p = 1; p < numPoints && joinSize; ++p) { 4121 PetscInt newJoinSize = 0; 4122 4123 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4124 for (c = 0; c < dof; ++c) { 4125 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4126 4127 for (m = 0; m < joinSize; ++m) { 4128 if (point == join[i][m]) { 4129 join[1-i][newJoinSize++] = point; 4130 break; 4131 } 4132 } 4133 } 4134 joinSize = newJoinSize; 4135 i = 1-i; 4136 } 4137 if (joinSize) break; 4138 } 4139 *numCoveredPoints = joinSize; 4140 *coveredPoints = join[i]; 4141 for (p = 0; p < numPoints; ++p) { 4142 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 4143 } 4144 ierr = PetscFree(closures);CHKERRQ(ierr); 4145 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4146 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4147 PetscFunctionReturn(0); 4148 } 4149 4150 /*@C 4151 DMPlexGetMeet - Get an array for the meet of the set of points 4152 4153 Not Collective 4154 4155 Input Parameters: 4156 + dm - The DMPlex object 4157 . numPoints - The number of input points for the meet 4158 - points - The input points 4159 4160 Output Parameters: 4161 + numCoveredPoints - The number of points in the meet 4162 - coveredPoints - The points in the meet 4163 4164 Level: intermediate 4165 4166 Note: Currently, this is restricted to a single level meet 4167 4168 Fortran Notes: 4169 Since it returns an array, this routine is only available in Fortran 90, and you must 4170 include petsc.h90 in your code. 4171 4172 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4173 4174 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 4175 @*/ 4176 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4177 { 4178 DM_Plex *mesh = (DM_Plex*) dm->data; 4179 PetscInt *meet[2]; 4180 PetscInt meetSize, i = 0; 4181 PetscInt dof, off, p, c, m; 4182 PetscErrorCode ierr; 4183 4184 PetscFunctionBegin; 4185 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4186 PetscValidPointer(points, 3); 4187 PetscValidPointer(numCoveringPoints, 4); 4188 PetscValidPointer(coveringPoints, 5); 4189 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4190 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4191 /* Copy in cone of first point */ 4192 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 4193 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 4194 for (meetSize = 0; meetSize < dof; ++meetSize) { 4195 meet[i][meetSize] = mesh->cones[off+meetSize]; 4196 } 4197 /* Check each successive cone */ 4198 for (p = 1; p < numPoints; ++p) { 4199 PetscInt newMeetSize = 0; 4200 4201 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 4202 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 4203 for (c = 0; c < dof; ++c) { 4204 const PetscInt point = mesh->cones[off+c]; 4205 4206 for (m = 0; m < meetSize; ++m) { 4207 if (point == meet[i][m]) { 4208 meet[1-i][newMeetSize++] = point; 4209 break; 4210 } 4211 } 4212 } 4213 meetSize = newMeetSize; 4214 i = 1-i; 4215 } 4216 *numCoveringPoints = meetSize; 4217 *coveringPoints = meet[i]; 4218 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4219 PetscFunctionReturn(0); 4220 } 4221 4222 /*@C 4223 DMPlexRestoreMeet - Restore an array for the meet of the set of points 4224 4225 Not Collective 4226 4227 Input Parameters: 4228 + dm - The DMPlex object 4229 . numPoints - The number of input points for the meet 4230 - points - The input points 4231 4232 Output Parameters: 4233 + numCoveredPoints - The number of points in the meet 4234 - coveredPoints - The points in the meet 4235 4236 Level: intermediate 4237 4238 Fortran Notes: 4239 Since it returns an array, this routine is only available in Fortran 90, and you must 4240 include petsc.h90 in your code. 4241 4242 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4243 4244 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 4245 @*/ 4246 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4247 { 4248 PetscErrorCode ierr; 4249 4250 PetscFunctionBegin; 4251 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4252 if (points) PetscValidIntPointer(points,3); 4253 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4254 PetscValidPointer(coveredPoints,5); 4255 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4256 if (numCoveredPoints) *numCoveredPoints = 0; 4257 PetscFunctionReturn(0); 4258 } 4259 4260 /*@C 4261 DMPlexGetFullMeet - Get an array for the meet of the set of points 4262 4263 Not Collective 4264 4265 Input Parameters: 4266 + dm - The DMPlex object 4267 . numPoints - The number of input points for the meet 4268 - points - The input points 4269 4270 Output Parameters: 4271 + numCoveredPoints - The number of points in the meet 4272 - coveredPoints - The points in the meet 4273 4274 Level: intermediate 4275 4276 Fortran Notes: 4277 Since it returns an array, this routine is only available in Fortran 90, and you must 4278 include petsc.h90 in your code. 4279 4280 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4281 4282 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 4283 @*/ 4284 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4285 { 4286 DM_Plex *mesh = (DM_Plex*) dm->data; 4287 PetscInt *offsets, **closures; 4288 PetscInt *meet[2]; 4289 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 4290 PetscInt p, h, c, m, mc; 4291 PetscErrorCode ierr; 4292 4293 PetscFunctionBegin; 4294 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4295 PetscValidPointer(points, 3); 4296 PetscValidPointer(numCoveredPoints, 4); 4297 PetscValidPointer(coveredPoints, 5); 4298 4299 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 4300 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 4301 ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4302 mc = mesh->maxConeSize; 4303 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 4304 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4305 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4306 4307 for (p = 0; p < numPoints; ++p) { 4308 PetscInt closureSize; 4309 4310 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 4311 4312 offsets[p*(height+2)+0] = 0; 4313 for (h = 0; h < height+1; ++h) { 4314 PetscInt pStart, pEnd, i; 4315 4316 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 4317 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4318 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4319 offsets[p*(height+2)+h+1] = i; 4320 break; 4321 } 4322 } 4323 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4324 } 4325 if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 4326 } 4327 for (h = 0; h < height+1; ++h) { 4328 PetscInt dof; 4329 4330 /* Copy in cone of first point */ 4331 dof = offsets[h+1] - offsets[h]; 4332 for (meetSize = 0; meetSize < dof; ++meetSize) { 4333 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4334 } 4335 /* Check each successive cone */ 4336 for (p = 1; p < numPoints && meetSize; ++p) { 4337 PetscInt newMeetSize = 0; 4338 4339 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4340 for (c = 0; c < dof; ++c) { 4341 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4342 4343 for (m = 0; m < meetSize; ++m) { 4344 if (point == meet[i][m]) { 4345 meet[1-i][newMeetSize++] = point; 4346 break; 4347 } 4348 } 4349 } 4350 meetSize = newMeetSize; 4351 i = 1-i; 4352 } 4353 if (meetSize) break; 4354 } 4355 *numCoveredPoints = meetSize; 4356 *coveredPoints = meet[i]; 4357 for (p = 0; p < numPoints; ++p) { 4358 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 4359 } 4360 ierr = PetscFree(closures);CHKERRQ(ierr); 4361 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4362 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4363 PetscFunctionReturn(0); 4364 } 4365 4366 /*@C 4367 DMPlexEqual - Determine if two DMs have the same topology 4368 4369 Not Collective 4370 4371 Input Parameters: 4372 + dmA - A DMPlex object 4373 - dmB - A DMPlex object 4374 4375 Output Parameters: 4376 . equal - PETSC_TRUE if the topologies are identical 4377 4378 Level: intermediate 4379 4380 Notes: 4381 We are not solving graph isomorphism, so we do not permutation. 4382 4383 .seealso: DMPlexGetCone() 4384 @*/ 4385 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 4386 { 4387 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 4388 PetscErrorCode ierr; 4389 4390 PetscFunctionBegin; 4391 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 4392 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4393 PetscValidPointer(equal, 3); 4394 4395 *equal = PETSC_FALSE; 4396 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 4397 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 4398 if (depth != depthB) PetscFunctionReturn(0); 4399 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 4400 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 4401 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 4402 for (p = pStart; p < pEnd; ++p) { 4403 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 4404 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 4405 4406 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 4407 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 4408 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 4409 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 4410 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 4411 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 4412 if (coneSize != coneSizeB) PetscFunctionReturn(0); 4413 for (c = 0; c < coneSize; ++c) { 4414 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 4415 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 4416 } 4417 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 4418 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 4419 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 4420 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 4421 if (supportSize != supportSizeB) PetscFunctionReturn(0); 4422 for (s = 0; s < supportSize; ++s) { 4423 if (support[s] != supportB[s]) PetscFunctionReturn(0); 4424 } 4425 } 4426 *equal = PETSC_TRUE; 4427 PetscFunctionReturn(0); 4428 } 4429 4430 /*@C 4431 DMPlexGetNumFaceVertices - Returns the number of vertices on a face 4432 4433 Not Collective 4434 4435 Input Parameters: 4436 + dm - The DMPlex 4437 . cellDim - The cell dimension 4438 - numCorners - The number of vertices on a cell 4439 4440 Output Parameters: 4441 . numFaceVertices - The number of vertices on a face 4442 4443 Level: developer 4444 4445 Notes: 4446 Of course this can only work for a restricted set of symmetric shapes 4447 4448 .seealso: DMPlexGetCone() 4449 @*/ 4450 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4451 { 4452 MPI_Comm comm; 4453 PetscErrorCode ierr; 4454 4455 PetscFunctionBegin; 4456 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4457 PetscValidPointer(numFaceVertices,4); 4458 switch (cellDim) { 4459 case 0: 4460 *numFaceVertices = 0; 4461 break; 4462 case 1: 4463 *numFaceVertices = 1; 4464 break; 4465 case 2: 4466 switch (numCorners) { 4467 case 3: /* triangle */ 4468 *numFaceVertices = 2; /* Edge has 2 vertices */ 4469 break; 4470 case 4: /* quadrilateral */ 4471 *numFaceVertices = 2; /* Edge has 2 vertices */ 4472 break; 4473 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 4474 *numFaceVertices = 3; /* Edge has 3 vertices */ 4475 break; 4476 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 4477 *numFaceVertices = 3; /* Edge has 3 vertices */ 4478 break; 4479 default: 4480 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4481 } 4482 break; 4483 case 3: 4484 switch (numCorners) { 4485 case 4: /* tetradehdron */ 4486 *numFaceVertices = 3; /* Face has 3 vertices */ 4487 break; 4488 case 6: /* tet cohesive cells */ 4489 *numFaceVertices = 4; /* Face has 4 vertices */ 4490 break; 4491 case 8: /* hexahedron */ 4492 *numFaceVertices = 4; /* Face has 4 vertices */ 4493 break; 4494 case 9: /* tet cohesive Lagrange cells */ 4495 *numFaceVertices = 6; /* Face has 6 vertices */ 4496 break; 4497 case 10: /* quadratic tetrahedron */ 4498 *numFaceVertices = 6; /* Face has 6 vertices */ 4499 break; 4500 case 12: /* hex cohesive Lagrange cells */ 4501 *numFaceVertices = 6; /* Face has 6 vertices */ 4502 break; 4503 case 18: /* quadratic tet cohesive Lagrange cells */ 4504 *numFaceVertices = 6; /* Face has 6 vertices */ 4505 break; 4506 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 4507 *numFaceVertices = 9; /* Face has 9 vertices */ 4508 break; 4509 default: 4510 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4511 } 4512 break; 4513 default: 4514 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 4515 } 4516 PetscFunctionReturn(0); 4517 } 4518 4519 /*@ 4520 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4521 4522 Not Collective 4523 4524 Input Parameter: 4525 . dm - The DMPlex object 4526 4527 Output Parameter: 4528 . depthLabel - The DMLabel recording point depth 4529 4530 Level: developer 4531 4532 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), 4533 @*/ 4534 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4535 { 4536 PetscFunctionBegin; 4537 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4538 PetscValidPointer(depthLabel, 2); 4539 *depthLabel = dm->depthLabel; 4540 PetscFunctionReturn(0); 4541 } 4542 4543 /*@ 4544 DMPlexGetDepth - Get the depth of the DAG representing this mesh 4545 4546 Not Collective 4547 4548 Input Parameter: 4549 . dm - The DMPlex object 4550 4551 Output Parameter: 4552 . depth - The number of strata (breadth first levels) in the DAG 4553 4554 Level: developer 4555 4556 Notes: 4557 This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4558 The point depth is described more in detail in DMPlexGetDepthStratum(). 4559 An empty mesh gives -1. 4560 4561 .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize() 4562 @*/ 4563 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4564 { 4565 DMLabel label; 4566 PetscInt d = 0; 4567 PetscErrorCode ierr; 4568 4569 PetscFunctionBegin; 4570 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4571 PetscValidPointer(depth, 2); 4572 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4573 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 4574 *depth = d-1; 4575 PetscFunctionReturn(0); 4576 } 4577 4578 /*@ 4579 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4580 4581 Not Collective 4582 4583 Input Parameters: 4584 + dm - The DMPlex object 4585 - stratumValue - The requested depth 4586 4587 Output Parameters: 4588 + start - The first point at this depth 4589 - end - One beyond the last point at this depth 4590 4591 Notes: 4592 Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4593 often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4594 higher dimension, e.g., "edges". 4595 4596 Level: developer 4597 4598 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate() 4599 @*/ 4600 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4601 { 4602 DMLabel label; 4603 PetscInt pStart, pEnd; 4604 PetscErrorCode ierr; 4605 4606 PetscFunctionBegin; 4607 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4608 if (start) {PetscValidPointer(start, 3); *start = 0;} 4609 if (end) {PetscValidPointer(end, 4); *end = 0;} 4610 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4611 if (pStart == pEnd) PetscFunctionReturn(0); 4612 if (stratumValue < 0) { 4613 if (start) *start = pStart; 4614 if (end) *end = pEnd; 4615 PetscFunctionReturn(0); 4616 } 4617 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4618 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4619 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 4620 PetscFunctionReturn(0); 4621 } 4622 4623 /*@ 4624 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4625 4626 Not Collective 4627 4628 Input Parameters: 4629 + dm - The DMPlex object 4630 - stratumValue - The requested height 4631 4632 Output Parameters: 4633 + start - The first point at this height 4634 - end - One beyond the last point at this height 4635 4636 Notes: 4637 Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4638 points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4639 stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4640 4641 Level: developer 4642 4643 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight() 4644 @*/ 4645 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4646 { 4647 DMLabel label; 4648 PetscInt depth, pStart, pEnd; 4649 PetscErrorCode ierr; 4650 4651 PetscFunctionBegin; 4652 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4653 if (start) {PetscValidPointer(start, 3); *start = 0;} 4654 if (end) {PetscValidPointer(end, 4); *end = 0;} 4655 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4656 if (pStart == pEnd) PetscFunctionReturn(0); 4657 if (stratumValue < 0) { 4658 if (start) *start = pStart; 4659 if (end) *end = pEnd; 4660 PetscFunctionReturn(0); 4661 } 4662 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4663 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4664 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 4665 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 4666 PetscFunctionReturn(0); 4667 } 4668 4669 /*@ 4670 DMPlexGetPointDepth - Get the depth of a given point 4671 4672 Not Collective 4673 4674 Input Parameter: 4675 + dm - The DMPlex object 4676 - point - The point 4677 4678 Output Parameter: 4679 . depth - The depth of the point 4680 4681 Level: intermediate 4682 4683 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight() 4684 @*/ 4685 PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4686 { 4687 PetscErrorCode ierr; 4688 4689 PetscFunctionBegin; 4690 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4691 PetscValidIntPointer(depth, 3); 4692 ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr); 4693 PetscFunctionReturn(0); 4694 } 4695 4696 /*@ 4697 DMPlexGetPointHeight - Get the height of a given point 4698 4699 Not Collective 4700 4701 Input Parameter: 4702 + dm - The DMPlex object 4703 - point - The point 4704 4705 Output Parameter: 4706 . height - The height of the point 4707 4708 Level: intermediate 4709 4710 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth() 4711 @*/ 4712 PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 4713 { 4714 PetscInt n, pDepth; 4715 PetscErrorCode ierr; 4716 4717 PetscFunctionBegin; 4718 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4719 PetscValidIntPointer(height, 3); 4720 ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr); 4721 ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr); 4722 *height = n - 1 - pDepth; /* DAG depth is n-1 */ 4723 PetscFunctionReturn(0); 4724 } 4725 4726 /*@ 4727 DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4728 4729 Not Collective 4730 4731 Input Parameter: 4732 . dm - The DMPlex object 4733 4734 Output Parameter: 4735 . celltypeLabel - The DMLabel recording cell polytope type 4736 4737 Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4738 DMCreateLabel(dm, "celltype") beforehand. 4739 4740 Level: developer 4741 4742 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel() 4743 @*/ 4744 PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4745 { 4746 PetscErrorCode ierr; 4747 4748 PetscFunctionBegin; 4749 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4750 PetscValidPointer(celltypeLabel, 2); 4751 if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);} 4752 *celltypeLabel = dm->celltypeLabel; 4753 PetscFunctionReturn(0); 4754 } 4755 4756 /*@ 4757 DMPlexGetCellType - Get the polytope type of a given cell 4758 4759 Not Collective 4760 4761 Input Parameter: 4762 + dm - The DMPlex object 4763 - cell - The cell 4764 4765 Output Parameter: 4766 . celltype - The polytope type of the cell 4767 4768 Level: intermediate 4769 4770 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth() 4771 @*/ 4772 PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4773 { 4774 DMLabel label; 4775 PetscInt ct; 4776 PetscErrorCode ierr; 4777 4778 PetscFunctionBegin; 4779 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4780 PetscValidPointer(celltype, 3); 4781 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4782 ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr); 4783 if (ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell); 4784 *celltype = (DMPolytopeType) ct; 4785 PetscFunctionReturn(0); 4786 } 4787 4788 /*@ 4789 DMPlexSetCellType - Set the polytope type of a given cell 4790 4791 Not Collective 4792 4793 Input Parameters: 4794 + dm - The DMPlex object 4795 . cell - The cell 4796 - celltype - The polytope type of the cell 4797 4798 Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 4799 is executed. This function will override the computed type. However, if automatic classification will not succeed 4800 and a user wants to manually specify all types, the classification must be disabled by calling 4801 DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 4802 4803 Level: advanced 4804 4805 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel() 4806 @*/ 4807 PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 4808 { 4809 DMLabel label; 4810 PetscErrorCode ierr; 4811 4812 PetscFunctionBegin; 4813 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4814 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4815 ierr = DMLabelSetValue(label, cell, celltype);CHKERRQ(ierr); 4816 PetscFunctionReturn(0); 4817 } 4818 4819 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 4820 { 4821 PetscSection section, s; 4822 Mat m; 4823 PetscInt maxHeight; 4824 PetscErrorCode ierr; 4825 4826 PetscFunctionBegin; 4827 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 4828 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 4829 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 4830 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 4831 ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr); 4832 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 4833 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 4834 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 4835 ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr); 4836 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 4837 ierr = MatDestroy(&m);CHKERRQ(ierr); 4838 4839 ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr); 4840 ierr = DMCreateDS(*cdm);CHKERRQ(ierr); 4841 PetscFunctionReturn(0); 4842 } 4843 4844 PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 4845 { 4846 Vec coordsLocal; 4847 DM coordsDM; 4848 PetscErrorCode ierr; 4849 4850 PetscFunctionBegin; 4851 *field = NULL; 4852 ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr); 4853 ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr); 4854 if (coordsLocal && coordsDM) { 4855 ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr); 4856 } 4857 PetscFunctionReturn(0); 4858 } 4859 4860 /*@C 4861 DMPlexGetConeSection - Return a section which describes the layout of cone data 4862 4863 Not Collective 4864 4865 Input Parameters: 4866 . dm - The DMPlex object 4867 4868 Output Parameter: 4869 . section - The PetscSection object 4870 4871 Level: developer 4872 4873 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 4874 @*/ 4875 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 4876 { 4877 DM_Plex *mesh = (DM_Plex*) dm->data; 4878 4879 PetscFunctionBegin; 4880 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4881 if (section) *section = mesh->coneSection; 4882 PetscFunctionReturn(0); 4883 } 4884 4885 /*@C 4886 DMPlexGetSupportSection - Return a section which describes the layout of support data 4887 4888 Not Collective 4889 4890 Input Parameters: 4891 . dm - The DMPlex object 4892 4893 Output Parameter: 4894 . section - The PetscSection object 4895 4896 Level: developer 4897 4898 .seealso: DMPlexGetConeSection() 4899 @*/ 4900 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 4901 { 4902 DM_Plex *mesh = (DM_Plex*) dm->data; 4903 4904 PetscFunctionBegin; 4905 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4906 if (section) *section = mesh->supportSection; 4907 PetscFunctionReturn(0); 4908 } 4909 4910 /*@C 4911 DMPlexGetCones - Return cone data 4912 4913 Not Collective 4914 4915 Input Parameters: 4916 . dm - The DMPlex object 4917 4918 Output Parameter: 4919 . cones - The cone for each point 4920 4921 Level: developer 4922 4923 .seealso: DMPlexGetConeSection() 4924 @*/ 4925 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 4926 { 4927 DM_Plex *mesh = (DM_Plex*) dm->data; 4928 4929 PetscFunctionBegin; 4930 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4931 if (cones) *cones = mesh->cones; 4932 PetscFunctionReturn(0); 4933 } 4934 4935 /*@C 4936 DMPlexGetConeOrientations - Return cone orientation data 4937 4938 Not Collective 4939 4940 Input Parameters: 4941 . dm - The DMPlex object 4942 4943 Output Parameter: 4944 . coneOrientations - The cone orientation for each point 4945 4946 Level: developer 4947 4948 .seealso: DMPlexGetConeSection() 4949 @*/ 4950 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 4951 { 4952 DM_Plex *mesh = (DM_Plex*) dm->data; 4953 4954 PetscFunctionBegin; 4955 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4956 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 4957 PetscFunctionReturn(0); 4958 } 4959 4960 /******************************** FEM Support **********************************/ 4961 4962 /* 4963 Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 4964 representing a line in the section. 4965 */ 4966 static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 4967 { 4968 PetscErrorCode ierr; 4969 4970 PetscFunctionBeginHot; 4971 ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr); 4972 if (line < 0) { 4973 *k = 0; 4974 *Nc = 0; 4975 } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 4976 *k = 1; 4977 } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 4978 /* An order k SEM disc has k-1 dofs on an edge */ 4979 ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr); 4980 *k = *k / *Nc + 1; 4981 } 4982 PetscFunctionReturn(0); 4983 } 4984 4985 /*@ 4986 4987 DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 4988 lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 4989 section provided (or the section of the DM). 4990 4991 Input Parameters: 4992 + dm - The DM 4993 . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 4994 - section - The PetscSection to reorder, or NULL for the default section 4995 4996 Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 4997 degree of the basis. 4998 4999 Example: 5000 A typical interpolated single-quad mesh might order points as 5001 .vb 5002 [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5003 5004 v4 -- e6 -- v3 5005 | | 5006 e7 c0 e8 5007 | | 5008 v1 -- e5 -- v2 5009 .ve 5010 5011 (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5012 dofs in the order of points, e.g., 5013 .vb 5014 c0 -> [0,1,2,3] 5015 v1 -> [4] 5016 ... 5017 e5 -> [8, 9] 5018 .ve 5019 5020 which corresponds to the dofs 5021 .vb 5022 6 10 11 7 5023 13 2 3 15 5024 12 0 1 14 5025 4 8 9 5 5026 .ve 5027 5028 The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5029 .vb 5030 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5031 .ve 5032 5033 After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5034 .vb 5035 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5036 .ve 5037 5038 Level: developer 5039 5040 .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection() 5041 @*/ 5042 PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5043 { 5044 DMLabel label; 5045 PetscInt dim, depth = -1, eStart = -1, Nf; 5046 PetscBool vertexchart; 5047 PetscErrorCode ierr; 5048 5049 PetscFunctionBegin; 5050 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5051 if (dim < 1) PetscFunctionReturn(0); 5052 if (point < 0) { 5053 PetscInt sStart,sEnd; 5054 5055 ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr); 5056 point = sEnd-sStart ? sStart : point; 5057 } 5058 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 5059 if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); } 5060 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5061 if (depth == 1) {eStart = point;} 5062 else if (depth == dim) { 5063 const PetscInt *cone; 5064 5065 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5066 if (dim == 2) eStart = cone[0]; 5067 else if (dim == 3) { 5068 const PetscInt *cone2; 5069 ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 5070 eStart = cone2[0]; 5071 } else SETERRQ3(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); 5072 } else if (depth >= 0) SETERRQ3(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); 5073 { /* Determine whether the chart covers all points or just vertices. */ 5074 PetscInt pStart,pEnd,cStart,cEnd; 5075 ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr); 5076 ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr); 5077 if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Just vertices */ 5078 else vertexchart = PETSC_FALSE; /* Assume all interpolated points are in chart */ 5079 } 5080 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5081 for (PetscInt d=1; d<=dim; d++) { 5082 PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5083 PetscInt *perm; 5084 5085 for (f = 0; f < Nf; ++f) { 5086 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5087 size += PetscPowInt(k+1, d)*Nc; 5088 } 5089 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 5090 for (f = 0; f < Nf; ++f) { 5091 switch (d) { 5092 case 1: 5093 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5094 /* 5095 Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5096 We want [ vtx0; edge of length k-1; vtx1 ] 5097 */ 5098 for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5099 for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5100 for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5101 foffset = offset; 5102 break; 5103 case 2: 5104 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 5105 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5106 /* The SEM order is 5107 5108 v_lb, {e_b}, v_rb, 5109 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 5110 v_lt, reverse {e_t}, v_rt 5111 */ 5112 { 5113 const PetscInt of = 0; 5114 const PetscInt oeb = of + PetscSqr(k-1); 5115 const PetscInt oer = oeb + (k-1); 5116 const PetscInt oet = oer + (k-1); 5117 const PetscInt oel = oet + (k-1); 5118 const PetscInt ovlb = oel + (k-1); 5119 const PetscInt ovrb = ovlb + 1; 5120 const PetscInt ovrt = ovrb + 1; 5121 const PetscInt ovlt = ovrt + 1; 5122 PetscInt o; 5123 5124 /* bottom */ 5125 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 5126 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5127 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 5128 /* middle */ 5129 for (i = 0; i < k-1; ++i) { 5130 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 5131 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; 5132 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 5133 } 5134 /* top */ 5135 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 5136 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5137 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 5138 foffset = offset; 5139 } 5140 break; 5141 case 3: 5142 /* The original hex closure is 5143 5144 {c, 5145 f_b, f_t, f_f, f_b, f_r, f_l, 5146 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 5147 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 5148 */ 5149 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5150 /* The SEM order is 5151 Bottom Slice 5152 v_blf, {e^{(k-1)-n}_bf}, v_brf, 5153 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 5154 v_blb, {e_bb}, v_brb, 5155 5156 Middle Slice (j) 5157 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 5158 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 5159 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 5160 5161 Top Slice 5162 v_tlf, {e_tf}, v_trf, 5163 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 5164 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 5165 */ 5166 { 5167 const PetscInt oc = 0; 5168 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 5169 const PetscInt oft = ofb + PetscSqr(k-1); 5170 const PetscInt off = oft + PetscSqr(k-1); 5171 const PetscInt ofk = off + PetscSqr(k-1); 5172 const PetscInt ofr = ofk + PetscSqr(k-1); 5173 const PetscInt ofl = ofr + PetscSqr(k-1); 5174 const PetscInt oebl = ofl + PetscSqr(k-1); 5175 const PetscInt oebb = oebl + (k-1); 5176 const PetscInt oebr = oebb + (k-1); 5177 const PetscInt oebf = oebr + (k-1); 5178 const PetscInt oetf = oebf + (k-1); 5179 const PetscInt oetr = oetf + (k-1); 5180 const PetscInt oetb = oetr + (k-1); 5181 const PetscInt oetl = oetb + (k-1); 5182 const PetscInt oerf = oetl + (k-1); 5183 const PetscInt oelf = oerf + (k-1); 5184 const PetscInt oelb = oelf + (k-1); 5185 const PetscInt oerb = oelb + (k-1); 5186 const PetscInt ovblf = oerb + (k-1); 5187 const PetscInt ovblb = ovblf + 1; 5188 const PetscInt ovbrb = ovblb + 1; 5189 const PetscInt ovbrf = ovbrb + 1; 5190 const PetscInt ovtlf = ovbrf + 1; 5191 const PetscInt ovtrf = ovtlf + 1; 5192 const PetscInt ovtrb = ovtrf + 1; 5193 const PetscInt ovtlb = ovtrb + 1; 5194 PetscInt o, n; 5195 5196 /* Bottom Slice */ 5197 /* bottom */ 5198 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 5199 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5200 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 5201 /* middle */ 5202 for (i = 0; i < k-1; ++i) { 5203 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5204 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;} 5205 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 5206 } 5207 /* top */ 5208 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 5209 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5210 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 5211 5212 /* Middle Slice */ 5213 for (j = 0; j < k-1; ++j) { 5214 /* bottom */ 5215 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 5216 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; 5217 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 5218 /* middle */ 5219 for (i = 0; i < k-1; ++i) { 5220 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 5221 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; 5222 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 5223 } 5224 /* top */ 5225 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 5226 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; 5227 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 5228 } 5229 5230 /* Top Slice */ 5231 /* bottom */ 5232 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 5233 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5234 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 5235 /* middle */ 5236 for (i = 0; i < k-1; ++i) { 5237 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 5238 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 5239 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 5240 } 5241 /* top */ 5242 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 5243 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5244 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 5245 5246 foffset = offset; 5247 } 5248 break; 5249 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d); 5250 } 5251 } 5252 if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 5253 /* Check permutation */ 5254 { 5255 PetscInt *check; 5256 5257 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 5258 for (i = 0; i < size; ++i) {check[i] = -1; if (perm[i] < 0 || perm[i] >= size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid permutation index p[%D] = %D", i, perm[i]);} 5259 for (i = 0; i < size; ++i) check[perm[i]] = i; 5260 for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 5261 ierr = PetscFree(check);CHKERRQ(ierr); 5262 } 5263 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 5264 } 5265 PetscFunctionReturn(0); 5266 } 5267 5268 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5269 { 5270 PetscDS prob; 5271 PetscInt depth, Nf, h; 5272 DMLabel label; 5273 PetscErrorCode ierr; 5274 5275 PetscFunctionBeginHot; 5276 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 5277 Nf = prob->Nf; 5278 label = dm->depthLabel; 5279 *dspace = NULL; 5280 if (field < Nf) { 5281 PetscObject disc = prob->disc[field]; 5282 5283 if (disc->classid == PETSCFE_CLASSID) { 5284 PetscDualSpace dsp; 5285 5286 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 5287 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 5288 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 5289 h = depth - 1 - h; 5290 if (h) { 5291 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 5292 } else { 5293 *dspace = dsp; 5294 } 5295 } 5296 } 5297 PetscFunctionReturn(0); 5298 } 5299 5300 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5301 { 5302 PetscScalar *array, *vArray; 5303 const PetscInt *cone, *coneO; 5304 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5305 PetscErrorCode ierr; 5306 5307 PetscFunctionBeginHot; 5308 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5309 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5310 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5311 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5312 if (!values || !*values) { 5313 if ((point >= pStart) && (point < pEnd)) { 5314 PetscInt dof; 5315 5316 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5317 size += dof; 5318 } 5319 for (p = 0; p < numPoints; ++p) { 5320 const PetscInt cp = cone[p]; 5321 PetscInt dof; 5322 5323 if ((cp < pStart) || (cp >= pEnd)) continue; 5324 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5325 size += dof; 5326 } 5327 if (!values) { 5328 if (csize) *csize = size; 5329 PetscFunctionReturn(0); 5330 } 5331 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 5332 } else { 5333 array = *values; 5334 } 5335 size = 0; 5336 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 5337 if ((point >= pStart) && (point < pEnd)) { 5338 PetscInt dof, off, d; 5339 PetscScalar *varr; 5340 5341 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5342 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5343 varr = &vArray[off]; 5344 for (d = 0; d < dof; ++d, ++offset) { 5345 array[offset] = varr[d]; 5346 } 5347 size += dof; 5348 } 5349 for (p = 0; p < numPoints; ++p) { 5350 const PetscInt cp = cone[p]; 5351 PetscInt o = coneO[p]; 5352 PetscInt dof, off, d; 5353 PetscScalar *varr; 5354 5355 if ((cp < pStart) || (cp >= pEnd)) continue; 5356 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5357 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 5358 varr = &vArray[off]; 5359 if (o >= 0) { 5360 for (d = 0; d < dof; ++d, ++offset) { 5361 array[offset] = varr[d]; 5362 } 5363 } else { 5364 for (d = dof-1; d >= 0; --d, ++offset) { 5365 array[offset] = varr[d]; 5366 } 5367 } 5368 size += dof; 5369 } 5370 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 5371 if (!*values) { 5372 if (csize) *csize = size; 5373 *values = array; 5374 } else { 5375 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5376 *csize = size; 5377 } 5378 PetscFunctionReturn(0); 5379 } 5380 5381 /* Compress out points not in the section */ 5382 PETSC_STATIC_INLINE PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 5383 { 5384 const PetscInt np = *numPoints; 5385 PetscInt pStart, pEnd, p, q; 5386 PetscErrorCode ierr; 5387 5388 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5389 for (p = 0, q = 0; p < np; ++p) { 5390 const PetscInt r = points[p*2]; 5391 if ((r >= pStart) && (r < pEnd)) { 5392 points[q*2] = r; 5393 points[q*2+1] = points[p*2+1]; 5394 ++q; 5395 } 5396 } 5397 *numPoints = q; 5398 return 0; 5399 } 5400 5401 static PetscErrorCode DMPlexTransitiveClosure_Hybrid_Internal(DM dm, PetscInt point, PetscInt np, PetscInt *numPoints, PetscInt **points) 5402 { 5403 const PetscInt *cone, *ornt; 5404 PetscInt *pts, *closure = NULL; 5405 PetscInt dim, coneSize, c, d, clSize, cl; 5406 PetscErrorCode ierr; 5407 5408 PetscFunctionBeginHot; 5409 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5410 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 5411 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5412 ierr = DMPlexGetConeOrientation(dm, point, &ornt);CHKERRQ(ierr); 5413 ierr = DMPlexGetTransitiveClosure(dm, cone[0], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 5414 ierr = DMGetWorkArray(dm, np*2, MPIU_INT, &pts);CHKERRQ(ierr); 5415 c = 0; 5416 pts[c*2+0] = point; 5417 pts[c*2+1] = 0; 5418 ++c; 5419 for (cl = 0; cl < clSize*2; cl += 2, ++c) {pts[c*2+0] = closure[cl]; pts[c*2+1] = closure[cl+1];} 5420 ierr = DMPlexGetTransitiveClosure(dm, cone[1], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 5421 for (cl = 0; cl < clSize*2; cl += 2, ++c) {pts[c*2+0] = closure[cl]; pts[c*2+1] = closure[cl+1];} 5422 ierr = DMPlexRestoreTransitiveClosure(dm, cone[0], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 5423 if (dim >= 2) { 5424 for (d = 2; d < coneSize; ++d, ++c) {pts[c*2+0] = cone[d]; pts[c*2+1] = ornt[d];} 5425 } 5426 if (dim >= 3) { 5427 for (d = 2; d < coneSize; ++d) { 5428 const PetscInt fpoint = cone[d]; 5429 const PetscInt *fcone; 5430 PetscInt fconeSize, fc, i; 5431 5432 ierr = DMPlexGetConeSize(dm, fpoint, &fconeSize);CHKERRQ(ierr); 5433 ierr = DMPlexGetCone(dm, fpoint, &fcone);CHKERRQ(ierr); 5434 for (fc = 0; fc < fconeSize; ++fc) { 5435 for (i = 0; i < c; ++i) if (pts[i*2] == fcone[fc]) break; 5436 if (i == c) {pts[c*2+0] = fcone[fc]; pts[c*2+1] = 0; ++c;} 5437 } 5438 } 5439 } 5440 if (c != np) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid closure for hybrid point %D, size %D != %D", point, c, np); 5441 *numPoints = np; 5442 *points = pts; 5443 PetscFunctionReturn(0); 5444 } 5445 5446 /* Compressed closure does not apply closure permutation */ 5447 PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5448 { 5449 const PetscInt *cla = NULL; 5450 PetscInt np, *pts = NULL; 5451 PetscErrorCode ierr; 5452 5453 PetscFunctionBeginHot; 5454 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 5455 if (*clPoints) { 5456 PetscInt dof, off; 5457 5458 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 5459 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 5460 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 5461 np = dof/2; 5462 pts = (PetscInt *) &cla[off]; 5463 } else { 5464 DMPolytopeType ct; 5465 5466 /* Do not make the label if it does not exist */ 5467 if (!dm->celltypeLabel) {ct = DM_POLYTOPE_POINT;} 5468 else {ierr = DMPlexGetCellType(dm, point, &ct);CHKERRQ(ierr);} 5469 switch (ct) { 5470 case DM_POLYTOPE_SEG_PRISM_TENSOR: 5471 ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 9, &np, &pts);CHKERRQ(ierr); 5472 break; 5473 case DM_POLYTOPE_TRI_PRISM_TENSOR: 5474 ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 21, &np, &pts);CHKERRQ(ierr); 5475 break; 5476 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 5477 ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 27, &np, &pts);CHKERRQ(ierr); 5478 break; 5479 default: 5480 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 5481 } 5482 ierr = CompressPoints_Private(section, &np, pts);CHKERRQ(ierr); 5483 } 5484 *numPoints = np; 5485 *points = pts; 5486 *clp = cla; 5487 PetscFunctionReturn(0); 5488 } 5489 5490 PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5491 { 5492 PetscErrorCode ierr; 5493 5494 PetscFunctionBeginHot; 5495 if (!*clPoints) { 5496 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 5497 } else { 5498 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 5499 } 5500 *numPoints = 0; 5501 *points = NULL; 5502 *clSec = NULL; 5503 *clPoints = NULL; 5504 *clp = NULL; 5505 PetscFunctionReturn(0); 5506 } 5507 5508 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 5509 { 5510 PetscInt offset = 0, p; 5511 const PetscInt **perms = NULL; 5512 const PetscScalar **flips = NULL; 5513 PetscErrorCode ierr; 5514 5515 PetscFunctionBeginHot; 5516 *size = 0; 5517 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5518 for (p = 0; p < numPoints; p++) { 5519 const PetscInt point = points[2*p]; 5520 const PetscInt *perm = perms ? perms[p] : NULL; 5521 const PetscScalar *flip = flips ? flips[p] : NULL; 5522 PetscInt dof, off, d; 5523 const PetscScalar *varr; 5524 5525 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5526 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5527 varr = &vArray[off]; 5528 if (clperm) { 5529 if (perm) { 5530 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 5531 } else { 5532 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 5533 } 5534 if (flip) { 5535 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 5536 } 5537 } else { 5538 if (perm) { 5539 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 5540 } else { 5541 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 5542 } 5543 if (flip) { 5544 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 5545 } 5546 } 5547 offset += dof; 5548 } 5549 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5550 *size = offset; 5551 PetscFunctionReturn(0); 5552 } 5553 5554 PETSC_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[]) 5555 { 5556 PetscInt offset = 0, f; 5557 PetscErrorCode ierr; 5558 5559 PetscFunctionBeginHot; 5560 *size = 0; 5561 for (f = 0; f < numFields; ++f) { 5562 PetscInt p; 5563 const PetscInt **perms = NULL; 5564 const PetscScalar **flips = NULL; 5565 5566 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5567 for (p = 0; p < numPoints; p++) { 5568 const PetscInt point = points[2*p]; 5569 PetscInt fdof, foff, b; 5570 const PetscScalar *varr; 5571 const PetscInt *perm = perms ? perms[p] : NULL; 5572 const PetscScalar *flip = flips ? flips[p] : NULL; 5573 5574 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5575 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5576 varr = &vArray[foff]; 5577 if (clperm) { 5578 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 5579 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 5580 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 5581 } else { 5582 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 5583 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 5584 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 5585 } 5586 offset += fdof; 5587 } 5588 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5589 } 5590 *size = offset; 5591 PetscFunctionReturn(0); 5592 } 5593 5594 /*@C 5595 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5596 5597 Not collective 5598 5599 Input Parameters: 5600 + dm - The DM 5601 . section - The section describing the layout in v, or NULL to use the default section 5602 . v - The local vector 5603 . point - The point in the DM 5604 . csize - The size of the input values array, or NULL 5605 - values - An array to use for the values, or NULL to have it allocated automatically 5606 5607 Output Parameters: 5608 + csize - The number of values in the closure 5609 - values - The array of values. If the user provided NULL, it is a borrowed array and should not be freed 5610 5611 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 5612 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 5613 $ assembly function, and a user may already have allocated storage for this operation. 5614 $ 5615 $ A typical use could be 5616 $ 5617 $ values = NULL; 5618 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5619 $ for (cl = 0; cl < clSize; ++cl) { 5620 $ <Compute on closure> 5621 $ } 5622 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5623 $ 5624 $ or 5625 $ 5626 $ PetscMalloc1(clMaxSize, &values); 5627 $ for (p = pStart; p < pEnd; ++p) { 5628 $ clSize = clMaxSize; 5629 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5630 $ for (cl = 0; cl < clSize; ++cl) { 5631 $ <Compute on closure> 5632 $ } 5633 $ } 5634 $ PetscFree(values); 5635 5636 Fortran Notes: 5637 Since it returns an array, this routine is only available in Fortran 90, and you must 5638 include petsc.h90 in your code. 5639 5640 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5641 5642 Level: intermediate 5643 5644 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5645 @*/ 5646 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5647 { 5648 PetscSection clSection; 5649 IS clPoints; 5650 PetscInt *points = NULL; 5651 const PetscInt *clp, *perm; 5652 PetscInt depth, numFields, numPoints, asize; 5653 PetscErrorCode ierr; 5654 5655 PetscFunctionBeginHot; 5656 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5657 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5658 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5659 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5660 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5661 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5662 if (depth == 1 && numFields < 2) { 5663 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5664 PetscFunctionReturn(0); 5665 } 5666 /* Get points */ 5667 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5668 /* Get sizes */ 5669 asize = 0; 5670 for (PetscInt p = 0; p < numPoints*2; p += 2) { 5671 PetscInt dof; 5672 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5673 asize += dof; 5674 } 5675 if (values) { 5676 const PetscScalar *vArray; 5677 PetscInt size; 5678 5679 if (*values) { 5680 if (PetscUnlikely(*csize < asize)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %D not sufficient to hold closure size %D", *csize, asize); 5681 } else {ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, values);CHKERRQ(ierr);} 5682 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm);CHKERRQ(ierr); 5683 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5684 /* Get values */ 5685 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values);CHKERRQ(ierr);} 5686 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values);CHKERRQ(ierr);} 5687 if (PetscUnlikely(asize != size)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size); 5688 /* Cleanup array */ 5689 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5690 } 5691 if (csize) *csize = asize; 5692 /* Cleanup points */ 5693 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5694 PetscFunctionReturn(0); 5695 } 5696 5697 PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5698 { 5699 DMLabel depthLabel; 5700 PetscSection clSection; 5701 IS clPoints; 5702 PetscScalar *array; 5703 const PetscScalar *vArray; 5704 PetscInt *points = NULL; 5705 const PetscInt *clp, *perm = NULL; 5706 PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5707 PetscErrorCode ierr; 5708 5709 PetscFunctionBeginHot; 5710 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5711 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5712 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5713 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5714 ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr); 5715 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 5716 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5717 if (mdepth == 1 && numFields < 2) { 5718 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5719 PetscFunctionReturn(0); 5720 } 5721 /* Get points */ 5722 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5723 for (clsize=0,p=0; p<Np; p++) { 5724 PetscInt dof; 5725 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 5726 clsize += dof; 5727 } 5728 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm);CHKERRQ(ierr); 5729 /* Filter points */ 5730 for (p = 0; p < numPoints*2; p += 2) { 5731 PetscInt dep; 5732 5733 ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr); 5734 if (dep != depth) continue; 5735 points[Np*2+0] = points[p]; 5736 points[Np*2+1] = points[p+1]; 5737 ++Np; 5738 } 5739 /* Get array */ 5740 if (!values || !*values) { 5741 PetscInt asize = 0, dof; 5742 5743 for (p = 0; p < Np*2; p += 2) { 5744 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5745 asize += dof; 5746 } 5747 if (!values) { 5748 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5749 if (csize) *csize = asize; 5750 PetscFunctionReturn(0); 5751 } 5752 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 5753 } else { 5754 array = *values; 5755 } 5756 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5757 /* Get values */ 5758 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 5759 else {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);} 5760 /* Cleanup points */ 5761 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5762 /* Cleanup array */ 5763 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5764 if (!*values) { 5765 if (csize) *csize = size; 5766 *values = array; 5767 } else { 5768 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5769 *csize = size; 5770 } 5771 PetscFunctionReturn(0); 5772 } 5773 5774 /*@C 5775 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5776 5777 Not collective 5778 5779 Input Parameters: 5780 + dm - The DM 5781 . section - The section describing the layout in v, or NULL to use the default section 5782 . v - The local vector 5783 . point - The point in the DM 5784 . csize - The number of values in the closure, or NULL 5785 - values - The array of values, which is a borrowed array and should not be freed 5786 5787 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 5788 5789 Fortran Notes: 5790 Since it returns an array, this routine is only available in Fortran 90, and you must 5791 include petsc.h90 in your code. 5792 5793 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5794 5795 Level: intermediate 5796 5797 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5798 @*/ 5799 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5800 { 5801 PetscInt size = 0; 5802 PetscErrorCode ierr; 5803 5804 PetscFunctionBegin; 5805 /* Should work without recalculating size */ 5806 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 5807 *values = NULL; 5808 PetscFunctionReturn(0); 5809 } 5810 5811 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 5812 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5813 5814 PETSC_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[]) 5815 { 5816 PetscInt cdof; /* The number of constraints on this point */ 5817 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5818 PetscScalar *a; 5819 PetscInt off, cind = 0, k; 5820 PetscErrorCode ierr; 5821 5822 PetscFunctionBegin; 5823 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5824 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5825 a = &array[off]; 5826 if (!cdof || setBC) { 5827 if (clperm) { 5828 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 5829 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5830 } else { 5831 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 5832 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5833 } 5834 } else { 5835 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5836 if (clperm) { 5837 if (perm) {for (k = 0; k < dof; ++k) { 5838 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5839 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5840 } 5841 } else { 5842 for (k = 0; k < dof; ++k) { 5843 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5844 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5845 } 5846 } 5847 } else { 5848 if (perm) { 5849 for (k = 0; k < dof; ++k) { 5850 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5851 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5852 } 5853 } else { 5854 for (k = 0; k < dof; ++k) { 5855 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5856 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5857 } 5858 } 5859 } 5860 } 5861 PetscFunctionReturn(0); 5862 } 5863 5864 PETSC_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[]) 5865 { 5866 PetscInt cdof; /* The number of constraints on this point */ 5867 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5868 PetscScalar *a; 5869 PetscInt off, cind = 0, k; 5870 PetscErrorCode ierr; 5871 5872 PetscFunctionBegin; 5873 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5874 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5875 a = &array[off]; 5876 if (cdof) { 5877 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5878 if (clperm) { 5879 if (perm) { 5880 for (k = 0; k < dof; ++k) { 5881 if ((cind < cdof) && (k == cdofs[cind])) { 5882 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5883 cind++; 5884 } 5885 } 5886 } else { 5887 for (k = 0; k < dof; ++k) { 5888 if ((cind < cdof) && (k == cdofs[cind])) { 5889 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5890 cind++; 5891 } 5892 } 5893 } 5894 } else { 5895 if (perm) { 5896 for (k = 0; k < dof; ++k) { 5897 if ((cind < cdof) && (k == cdofs[cind])) { 5898 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5899 cind++; 5900 } 5901 } 5902 } else { 5903 for (k = 0; k < dof; ++k) { 5904 if ((cind < cdof) && (k == cdofs[cind])) { 5905 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5906 cind++; 5907 } 5908 } 5909 } 5910 } 5911 } 5912 PetscFunctionReturn(0); 5913 } 5914 5915 PETSC_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[]) 5916 { 5917 PetscScalar *a; 5918 PetscInt fdof, foff, fcdof, foffset = *offset; 5919 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5920 PetscInt cind = 0, b; 5921 PetscErrorCode ierr; 5922 5923 PetscFunctionBegin; 5924 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5925 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 5926 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5927 a = &array[foff]; 5928 if (!fcdof || setBC) { 5929 if (clperm) { 5930 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 5931 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 5932 } else { 5933 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 5934 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 5935 } 5936 } else { 5937 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5938 if (clperm) { 5939 if (perm) { 5940 for (b = 0; b < fdof; b++) { 5941 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5942 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 5943 } 5944 } else { 5945 for (b = 0; b < fdof; b++) { 5946 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5947 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 5948 } 5949 } 5950 } else { 5951 if (perm) { 5952 for (b = 0; b < fdof; b++) { 5953 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5954 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 5955 } 5956 } else { 5957 for (b = 0; b < fdof; b++) { 5958 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5959 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 5960 } 5961 } 5962 } 5963 } 5964 *offset += fdof; 5965 PetscFunctionReturn(0); 5966 } 5967 5968 PETSC_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[]) 5969 { 5970 PetscScalar *a; 5971 PetscInt fdof, foff, fcdof, foffset = *offset; 5972 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5973 PetscInt Nc, cind = 0, ncind = 0, b; 5974 PetscBool ncSet, fcSet; 5975 PetscErrorCode ierr; 5976 5977 PetscFunctionBegin; 5978 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 5979 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5980 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 5981 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5982 a = &array[foff]; 5983 if (fcdof) { 5984 /* We just override fcdof and fcdofs with Ncc and comps */ 5985 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5986 if (clperm) { 5987 if (perm) { 5988 if (comps) { 5989 for (b = 0; b < fdof; b++) { 5990 ncSet = fcSet = PETSC_FALSE; 5991 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5992 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5993 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 5994 } 5995 } else { 5996 for (b = 0; b < fdof; b++) { 5997 if ((cind < fcdof) && (b == fcdofs[cind])) { 5998 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 5999 ++cind; 6000 } 6001 } 6002 } 6003 } else { 6004 if (comps) { 6005 for (b = 0; b < fdof; b++) { 6006 ncSet = fcSet = PETSC_FALSE; 6007 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6008 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6009 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 6010 } 6011 } else { 6012 for (b = 0; b < fdof; b++) { 6013 if ((cind < fcdof) && (b == fcdofs[cind])) { 6014 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6015 ++cind; 6016 } 6017 } 6018 } 6019 } 6020 } else { 6021 if (perm) { 6022 if (comps) { 6023 for (b = 0; b < fdof; b++) { 6024 ncSet = fcSet = PETSC_FALSE; 6025 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6026 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6027 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 6028 } 6029 } else { 6030 for (b = 0; b < fdof; b++) { 6031 if ((cind < fcdof) && (b == fcdofs[cind])) { 6032 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6033 ++cind; 6034 } 6035 } 6036 } 6037 } else { 6038 if (comps) { 6039 for (b = 0; b < fdof; b++) { 6040 ncSet = fcSet = PETSC_FALSE; 6041 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6042 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6043 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 6044 } 6045 } else { 6046 for (b = 0; b < fdof; b++) { 6047 if ((cind < fcdof) && (b == fcdofs[cind])) { 6048 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6049 ++cind; 6050 } 6051 } 6052 } 6053 } 6054 } 6055 } 6056 *offset += fdof; 6057 PetscFunctionReturn(0); 6058 } 6059 6060 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6061 { 6062 PetscScalar *array; 6063 const PetscInt *cone, *coneO; 6064 PetscInt pStart, pEnd, p, numPoints, off, dof; 6065 PetscErrorCode ierr; 6066 6067 PetscFunctionBeginHot; 6068 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6069 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 6070 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 6071 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 6072 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6073 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6074 const PetscInt cp = !p ? point : cone[p-1]; 6075 const PetscInt o = !p ? 0 : coneO[p-1]; 6076 6077 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 6078 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 6079 /* ADD_VALUES */ 6080 { 6081 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6082 PetscScalar *a; 6083 PetscInt cdof, coff, cind = 0, k; 6084 6085 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 6086 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 6087 a = &array[coff]; 6088 if (!cdof) { 6089 if (o >= 0) { 6090 for (k = 0; k < dof; ++k) { 6091 a[k] += values[off+k]; 6092 } 6093 } else { 6094 for (k = 0; k < dof; ++k) { 6095 a[k] += values[off+dof-k-1]; 6096 } 6097 } 6098 } else { 6099 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 6100 if (o >= 0) { 6101 for (k = 0; k < dof; ++k) { 6102 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6103 a[k] += values[off+k]; 6104 } 6105 } else { 6106 for (k = 0; k < dof; ++k) { 6107 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6108 a[k] += values[off+dof-k-1]; 6109 } 6110 } 6111 } 6112 } 6113 } 6114 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6115 PetscFunctionReturn(0); 6116 } 6117 6118 /*@C 6119 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6120 6121 Not collective 6122 6123 Input Parameters: 6124 + dm - The DM 6125 . section - The section describing the layout in v, or NULL to use the default section 6126 . v - The local vector 6127 . point - The point in the DM 6128 . values - The array of values 6129 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 6130 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 6131 6132 Fortran Notes: 6133 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6134 6135 Level: intermediate 6136 6137 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6138 @*/ 6139 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6140 { 6141 PetscSection clSection; 6142 IS clPoints; 6143 PetscScalar *array; 6144 PetscInt *points = NULL; 6145 const PetscInt *clp, *clperm = NULL; 6146 PetscInt depth, numFields, numPoints, p, clsize; 6147 PetscErrorCode ierr; 6148 6149 PetscFunctionBeginHot; 6150 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6151 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6152 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6153 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6154 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6155 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6156 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 6157 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 6158 PetscFunctionReturn(0); 6159 } 6160 /* Get points */ 6161 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6162 for (clsize=0,p=0; p<numPoints; p++) { 6163 PetscInt dof; 6164 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 6165 clsize += dof; 6166 } 6167 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 6168 /* Get array */ 6169 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6170 /* Get values */ 6171 if (numFields > 0) { 6172 PetscInt offset = 0, f; 6173 for (f = 0; f < numFields; ++f) { 6174 const PetscInt **perms = NULL; 6175 const PetscScalar **flips = NULL; 6176 6177 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6178 switch (mode) { 6179 case INSERT_VALUES: 6180 for (p = 0; p < numPoints; p++) { 6181 const PetscInt point = points[2*p]; 6182 const PetscInt *perm = perms ? perms[p] : NULL; 6183 const PetscScalar *flip = flips ? flips[p] : NULL; 6184 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6185 } break; 6186 case INSERT_ALL_VALUES: 6187 for (p = 0; p < numPoints; p++) { 6188 const PetscInt point = points[2*p]; 6189 const PetscInt *perm = perms ? perms[p] : NULL; 6190 const PetscScalar *flip = flips ? flips[p] : NULL; 6191 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6192 } break; 6193 case INSERT_BC_VALUES: 6194 for (p = 0; p < numPoints; p++) { 6195 const PetscInt point = points[2*p]; 6196 const PetscInt *perm = perms ? perms[p] : NULL; 6197 const PetscScalar *flip = flips ? flips[p] : NULL; 6198 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6199 } break; 6200 case ADD_VALUES: 6201 for (p = 0; p < numPoints; p++) { 6202 const PetscInt point = points[2*p]; 6203 const PetscInt *perm = perms ? perms[p] : NULL; 6204 const PetscScalar *flip = flips ? flips[p] : NULL; 6205 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6206 } break; 6207 case ADD_ALL_VALUES: 6208 for (p = 0; p < numPoints; p++) { 6209 const PetscInt point = points[2*p]; 6210 const PetscInt *perm = perms ? perms[p] : NULL; 6211 const PetscScalar *flip = flips ? flips[p] : NULL; 6212 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6213 } break; 6214 case ADD_BC_VALUES: 6215 for (p = 0; p < numPoints; p++) { 6216 const PetscInt point = points[2*p]; 6217 const PetscInt *perm = perms ? perms[p] : NULL; 6218 const PetscScalar *flip = flips ? flips[p] : NULL; 6219 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6220 } break; 6221 default: 6222 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6223 } 6224 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6225 } 6226 } else { 6227 PetscInt dof, off; 6228 const PetscInt **perms = NULL; 6229 const PetscScalar **flips = NULL; 6230 6231 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6232 switch (mode) { 6233 case INSERT_VALUES: 6234 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6235 const PetscInt point = points[2*p]; 6236 const PetscInt *perm = perms ? perms[p] : NULL; 6237 const PetscScalar *flip = flips ? flips[p] : NULL; 6238 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6239 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6240 } break; 6241 case INSERT_ALL_VALUES: 6242 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6243 const PetscInt point = points[2*p]; 6244 const PetscInt *perm = perms ? perms[p] : NULL; 6245 const PetscScalar *flip = flips ? flips[p] : NULL; 6246 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6247 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6248 } break; 6249 case INSERT_BC_VALUES: 6250 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6251 const PetscInt point = points[2*p]; 6252 const PetscInt *perm = perms ? perms[p] : NULL; 6253 const PetscScalar *flip = flips ? flips[p] : NULL; 6254 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6255 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6256 } break; 6257 case ADD_VALUES: 6258 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6259 const PetscInt point = points[2*p]; 6260 const PetscInt *perm = perms ? perms[p] : NULL; 6261 const PetscScalar *flip = flips ? flips[p] : NULL; 6262 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6263 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6264 } break; 6265 case ADD_ALL_VALUES: 6266 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6267 const PetscInt point = points[2*p]; 6268 const PetscInt *perm = perms ? perms[p] : NULL; 6269 const PetscScalar *flip = flips ? flips[p] : NULL; 6270 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6271 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6272 } break; 6273 case ADD_BC_VALUES: 6274 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6275 const PetscInt point = points[2*p]; 6276 const PetscInt *perm = perms ? perms[p] : NULL; 6277 const PetscScalar *flip = flips ? flips[p] : NULL; 6278 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6279 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6280 } break; 6281 default: 6282 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6283 } 6284 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6285 } 6286 /* Cleanup points */ 6287 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6288 /* Cleanup array */ 6289 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6290 PetscFunctionReturn(0); 6291 } 6292 6293 /* Check whether the given point is in the label. If not, update the offset to skip this point */ 6294 PETSC_STATIC_INLINE PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 6295 { 6296 PetscFunctionBegin; 6297 if (label) { 6298 PetscInt val, fdof; 6299 PetscErrorCode ierr; 6300 6301 /* There is a problem with this: 6302 Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that 6303 touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell. 6304 Thus I am only going to check val != -1, not val != labelId 6305 */ 6306 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 6307 if (val < 0) { 6308 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6309 *offset += fdof; 6310 PetscFunctionReturn(1); 6311 } 6312 } 6313 PetscFunctionReturn(0); 6314 } 6315 6316 /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 6317 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) 6318 { 6319 PetscSection clSection; 6320 IS clPoints; 6321 PetscScalar *array; 6322 PetscInt *points = NULL; 6323 const PetscInt *clp; 6324 PetscInt numFields, numPoints, p; 6325 PetscInt offset = 0, f; 6326 PetscErrorCode ierr; 6327 6328 PetscFunctionBeginHot; 6329 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6330 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6331 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6332 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6333 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6334 /* Get points */ 6335 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6336 /* Get array */ 6337 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6338 /* Get values */ 6339 for (f = 0; f < numFields; ++f) { 6340 const PetscInt **perms = NULL; 6341 const PetscScalar **flips = NULL; 6342 6343 if (!fieldActive[f]) { 6344 for (p = 0; p < numPoints*2; p += 2) { 6345 PetscInt fdof; 6346 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6347 offset += fdof; 6348 } 6349 continue; 6350 } 6351 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6352 switch (mode) { 6353 case INSERT_VALUES: 6354 for (p = 0; p < numPoints; p++) { 6355 const PetscInt point = points[2*p]; 6356 const PetscInt *perm = perms ? perms[p] : NULL; 6357 const PetscScalar *flip = flips ? flips[p] : NULL; 6358 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6359 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array); 6360 } break; 6361 case INSERT_ALL_VALUES: 6362 for (p = 0; p < numPoints; p++) { 6363 const PetscInt point = points[2*p]; 6364 const PetscInt *perm = perms ? perms[p] : NULL; 6365 const PetscScalar *flip = flips ? flips[p] : NULL; 6366 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6367 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array); 6368 } break; 6369 case INSERT_BC_VALUES: 6370 for (p = 0; p < numPoints; p++) { 6371 const PetscInt point = points[2*p]; 6372 const PetscInt *perm = perms ? perms[p] : NULL; 6373 const PetscScalar *flip = flips ? flips[p] : NULL; 6374 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6375 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array); 6376 } break; 6377 case ADD_VALUES: 6378 for (p = 0; p < numPoints; p++) { 6379 const PetscInt point = points[2*p]; 6380 const PetscInt *perm = perms ? perms[p] : NULL; 6381 const PetscScalar *flip = flips ? flips[p] : NULL; 6382 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6383 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array); 6384 } break; 6385 case ADD_ALL_VALUES: 6386 for (p = 0; p < numPoints; p++) { 6387 const PetscInt point = points[2*p]; 6388 const PetscInt *perm = perms ? perms[p] : NULL; 6389 const PetscScalar *flip = flips ? flips[p] : NULL; 6390 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6391 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array); 6392 } break; 6393 default: 6394 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6395 } 6396 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6397 } 6398 /* Cleanup points */ 6399 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6400 /* Cleanup array */ 6401 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6402 PetscFunctionReturn(0); 6403 } 6404 6405 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6406 { 6407 PetscMPIInt rank; 6408 PetscInt i, j; 6409 PetscErrorCode ierr; 6410 6411 PetscFunctionBegin; 6412 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr); 6413 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 6414 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 6415 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 6416 numCIndices = numCIndices ? numCIndices : numRIndices; 6417 if (!values) PetscFunctionReturn(0); 6418 for (i = 0; i < numRIndices; i++) { 6419 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 6420 for (j = 0; j < numCIndices; j++) { 6421 #if defined(PETSC_USE_COMPLEX) 6422 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 6423 #else 6424 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 6425 #endif 6426 } 6427 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6428 } 6429 PetscFunctionReturn(0); 6430 } 6431 6432 /* 6433 DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 6434 6435 Input Parameters: 6436 + section - The section for this data layout 6437 . islocal - Is the section (and thus indices being requested) local or global? 6438 . point - The point contributing dofs with these indices 6439 . off - The global offset of this point 6440 . loff - The local offset of each field 6441 . setBC - The flag determining whether to include indices of bounsary values 6442 . perm - A permutation of the dofs on this point, or NULL 6443 - indperm - A permutation of the entire indices array, or NULL 6444 6445 Output Parameter: 6446 . indices - Indices for dofs on this point 6447 6448 Level: developer 6449 6450 Note: The indices could be local or global, depending on the value of 'off'. 6451 */ 6452 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6453 { 6454 PetscInt dof; /* The number of unknowns on this point */ 6455 PetscInt cdof; /* The number of constraints on this point */ 6456 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6457 PetscInt cind = 0, k; 6458 PetscErrorCode ierr; 6459 6460 PetscFunctionBegin; 6461 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6462 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6463 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6464 if (!cdof || setBC) { 6465 for (k = 0; k < dof; ++k) { 6466 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6467 const PetscInt ind = indperm ? indperm[preind] : preind; 6468 6469 indices[ind] = off + k; 6470 } 6471 } else { 6472 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6473 for (k = 0; k < dof; ++k) { 6474 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6475 const PetscInt ind = indperm ? indperm[preind] : preind; 6476 6477 if ((cind < cdof) && (k == cdofs[cind])) { 6478 /* Insert check for returning constrained indices */ 6479 indices[ind] = -(off+k+1); 6480 ++cind; 6481 } else { 6482 indices[ind] = off + k - (islocal ? 0 : cind); 6483 } 6484 } 6485 } 6486 *loff += dof; 6487 PetscFunctionReturn(0); 6488 } 6489 6490 /* 6491 DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 6492 6493 Input Parameters: 6494 + section - a section (global or local) 6495 - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 6496 . point - point within section 6497 . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 6498 . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 6499 . setBC - identify constrained (boundary condition) points via involution. 6500 . perms - perms[f][permsoff][:] is a permutation of dofs within each field 6501 . permsoff - offset 6502 - indperm - index permutation 6503 6504 Output Parameter: 6505 . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 6506 . indices - array to hold indices (as defined by section) of each dof associated with point 6507 6508 Notes: 6509 If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 6510 If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 6511 in the local vector. 6512 6513 If section is global and setBC=false, the indices for constrained points are negative (and their value is not 6514 significant). It is invalid to call with a global section and setBC=true. 6515 6516 Developer Note: 6517 The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 6518 in the future, global sections may have fields set, in which case we could pass the global section and obtain the 6519 offset could be obtained from the section instead of passing it explicitly as we do now. 6520 6521 Example: 6522 Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 6523 When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 6524 Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 6525 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. 6526 6527 Level: developer 6528 */ 6529 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[]) 6530 { 6531 PetscInt numFields, foff, f; 6532 PetscErrorCode ierr; 6533 6534 PetscFunctionBegin; 6535 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6536 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6537 for (f = 0, foff = 0; f < numFields; ++f) { 6538 PetscInt fdof, cfdof; 6539 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6540 PetscInt cind = 0, b; 6541 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6542 6543 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6544 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6545 if (!cfdof || setBC) { 6546 for (b = 0; b < fdof; ++b) { 6547 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6548 const PetscInt ind = indperm ? indperm[preind] : preind; 6549 6550 indices[ind] = off+foff+b; 6551 } 6552 } else { 6553 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6554 for (b = 0; b < fdof; ++b) { 6555 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6556 const PetscInt ind = indperm ? indperm[preind] : preind; 6557 6558 if ((cind < cfdof) && (b == fcdofs[cind])) { 6559 indices[ind] = -(off+foff+b+1); 6560 ++cind; 6561 } else { 6562 indices[ind] = off + foff + b - (islocal ? 0 : cind); 6563 } 6564 } 6565 } 6566 foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6567 foffs[f] += fdof; 6568 } 6569 PetscFunctionReturn(0); 6570 } 6571 6572 /* 6573 This version believes the globalSection offsets for each field, rather than just the point offset 6574 6575 . foffs - The offset into 'indices' for each field, since it is segregated by field 6576 6577 Notes: 6578 The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6579 Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 6580 */ 6581 static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 6582 { 6583 PetscInt numFields, foff, f; 6584 PetscErrorCode ierr; 6585 6586 PetscFunctionBegin; 6587 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6588 for (f = 0; f < numFields; ++f) { 6589 PetscInt fdof, cfdof; 6590 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6591 PetscInt cind = 0, b; 6592 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6593 6594 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6595 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6596 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 6597 if (!cfdof) { 6598 for (b = 0; b < fdof; ++b) { 6599 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6600 const PetscInt ind = indperm ? indperm[preind] : preind; 6601 6602 indices[ind] = foff+b; 6603 } 6604 } else { 6605 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6606 for (b = 0; b < fdof; ++b) { 6607 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6608 const PetscInt ind = indperm ? indperm[preind] : preind; 6609 6610 if ((cind < cfdof) && (b == fcdofs[cind])) { 6611 indices[ind] = -(foff+b+1); 6612 ++cind; 6613 } else { 6614 indices[ind] = foff+b-cind; 6615 } 6616 } 6617 } 6618 foffs[f] += fdof; 6619 } 6620 PetscFunctionReturn(0); 6621 } 6622 6623 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) 6624 { 6625 Mat cMat; 6626 PetscSection aSec, cSec; 6627 IS aIS; 6628 PetscInt aStart = -1, aEnd = -1; 6629 const PetscInt *anchors; 6630 PetscInt numFields, f, p, q, newP = 0; 6631 PetscInt newNumPoints = 0, newNumIndices = 0; 6632 PetscInt *newPoints, *indices, *newIndices; 6633 PetscInt maxAnchor, maxDof; 6634 PetscInt newOffsets[32]; 6635 PetscInt *pointMatOffsets[32]; 6636 PetscInt *newPointOffsets[32]; 6637 PetscScalar *pointMat[32]; 6638 PetscScalar *newValues=NULL,*tmpValues; 6639 PetscBool anyConstrained = PETSC_FALSE; 6640 PetscErrorCode ierr; 6641 6642 PetscFunctionBegin; 6643 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6644 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6645 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6646 6647 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6648 /* if there are point-to-point constraints */ 6649 if (aSec) { 6650 ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr); 6651 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6652 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 6653 /* figure out how many points are going to be in the new element matrix 6654 * (we allow double counting, because it's all just going to be summed 6655 * into the global matrix anyway) */ 6656 for (p = 0; p < 2*numPoints; p+=2) { 6657 PetscInt b = points[p]; 6658 PetscInt bDof = 0, bSecDof; 6659 6660 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6661 if (!bSecDof) { 6662 continue; 6663 } 6664 if (b >= aStart && b < aEnd) { 6665 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 6666 } 6667 if (bDof) { 6668 /* this point is constrained */ 6669 /* it is going to be replaced by its anchors */ 6670 PetscInt bOff, q; 6671 6672 anyConstrained = PETSC_TRUE; 6673 newNumPoints += bDof; 6674 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 6675 for (q = 0; q < bDof; q++) { 6676 PetscInt a = anchors[bOff + q]; 6677 PetscInt aDof; 6678 6679 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6680 newNumIndices += aDof; 6681 for (f = 0; f < numFields; ++f) { 6682 PetscInt fDof; 6683 6684 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 6685 newOffsets[f+1] += fDof; 6686 } 6687 } 6688 } 6689 else { 6690 /* this point is not constrained */ 6691 newNumPoints++; 6692 newNumIndices += bSecDof; 6693 for (f = 0; f < numFields; ++f) { 6694 PetscInt fDof; 6695 6696 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6697 newOffsets[f+1] += fDof; 6698 } 6699 } 6700 } 6701 } 6702 if (!anyConstrained) { 6703 if (outNumPoints) *outNumPoints = 0; 6704 if (outNumIndices) *outNumIndices = 0; 6705 if (outPoints) *outPoints = NULL; 6706 if (outValues) *outValues = NULL; 6707 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6708 PetscFunctionReturn(0); 6709 } 6710 6711 if (outNumPoints) *outNumPoints = newNumPoints; 6712 if (outNumIndices) *outNumIndices = newNumIndices; 6713 6714 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6715 6716 if (!outPoints && !outValues) { 6717 if (offsets) { 6718 for (f = 0; f <= numFields; f++) { 6719 offsets[f] = newOffsets[f]; 6720 } 6721 } 6722 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6723 PetscFunctionReturn(0); 6724 } 6725 6726 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 6727 6728 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 6729 6730 /* workspaces */ 6731 if (numFields) { 6732 for (f = 0; f < numFields; f++) { 6733 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 6734 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6735 } 6736 } 6737 else { 6738 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 6739 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6740 } 6741 6742 /* get workspaces for the point-to-point matrices */ 6743 if (numFields) { 6744 PetscInt totalOffset, totalMatOffset; 6745 6746 for (p = 0; p < numPoints; p++) { 6747 PetscInt b = points[2*p]; 6748 PetscInt bDof = 0, bSecDof; 6749 6750 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6751 if (!bSecDof) { 6752 for (f = 0; f < numFields; f++) { 6753 newPointOffsets[f][p + 1] = 0; 6754 pointMatOffsets[f][p + 1] = 0; 6755 } 6756 continue; 6757 } 6758 if (b >= aStart && b < aEnd) { 6759 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6760 } 6761 if (bDof) { 6762 for (f = 0; f < numFields; f++) { 6763 PetscInt fDof, q, bOff, allFDof = 0; 6764 6765 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6766 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6767 for (q = 0; q < bDof; q++) { 6768 PetscInt a = anchors[bOff + q]; 6769 PetscInt aFDof; 6770 6771 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 6772 allFDof += aFDof; 6773 } 6774 newPointOffsets[f][p+1] = allFDof; 6775 pointMatOffsets[f][p+1] = fDof * allFDof; 6776 } 6777 } 6778 else { 6779 for (f = 0; f < numFields; f++) { 6780 PetscInt fDof; 6781 6782 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6783 newPointOffsets[f][p+1] = fDof; 6784 pointMatOffsets[f][p+1] = 0; 6785 } 6786 } 6787 } 6788 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 6789 newPointOffsets[f][0] = totalOffset; 6790 pointMatOffsets[f][0] = totalMatOffset; 6791 for (p = 0; p < numPoints; p++) { 6792 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6793 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6794 } 6795 totalOffset = newPointOffsets[f][numPoints]; 6796 totalMatOffset = pointMatOffsets[f][numPoints]; 6797 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 6798 } 6799 } 6800 else { 6801 for (p = 0; p < numPoints; p++) { 6802 PetscInt b = points[2*p]; 6803 PetscInt bDof = 0, bSecDof; 6804 6805 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6806 if (!bSecDof) { 6807 newPointOffsets[0][p + 1] = 0; 6808 pointMatOffsets[0][p + 1] = 0; 6809 continue; 6810 } 6811 if (b >= aStart && b < aEnd) { 6812 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6813 } 6814 if (bDof) { 6815 PetscInt bOff, q, allDof = 0; 6816 6817 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6818 for (q = 0; q < bDof; q++) { 6819 PetscInt a = anchors[bOff + q], aDof; 6820 6821 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 6822 allDof += aDof; 6823 } 6824 newPointOffsets[0][p+1] = allDof; 6825 pointMatOffsets[0][p+1] = bSecDof * allDof; 6826 } 6827 else { 6828 newPointOffsets[0][p+1] = bSecDof; 6829 pointMatOffsets[0][p+1] = 0; 6830 } 6831 } 6832 newPointOffsets[0][0] = 0; 6833 pointMatOffsets[0][0] = 0; 6834 for (p = 0; p < numPoints; p++) { 6835 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6836 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6837 } 6838 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 6839 } 6840 6841 /* output arrays */ 6842 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6843 6844 /* get the point-to-point matrices; construct newPoints */ 6845 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 6846 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6847 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 6848 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 6849 if (numFields) { 6850 for (p = 0, newP = 0; p < numPoints; p++) { 6851 PetscInt b = points[2*p]; 6852 PetscInt o = points[2*p+1]; 6853 PetscInt bDof = 0, bSecDof; 6854 6855 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6856 if (!bSecDof) { 6857 continue; 6858 } 6859 if (b >= aStart && b < aEnd) { 6860 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6861 } 6862 if (bDof) { 6863 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6864 6865 fStart[0] = 0; 6866 fEnd[0] = 0; 6867 for (f = 0; f < numFields; f++) { 6868 PetscInt fDof; 6869 6870 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 6871 fStart[f+1] = fStart[f] + fDof; 6872 fEnd[f+1] = fStart[f+1]; 6873 } 6874 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6875 ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 6876 6877 fAnchorStart[0] = 0; 6878 fAnchorEnd[0] = 0; 6879 for (f = 0; f < numFields; f++) { 6880 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 6881 6882 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 6883 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 6884 } 6885 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6886 for (q = 0; q < bDof; q++) { 6887 PetscInt a = anchors[bOff + q], aOff; 6888 6889 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6890 newPoints[2*(newP + q)] = a; 6891 newPoints[2*(newP + q) + 1] = 0; 6892 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 6893 ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 6894 } 6895 newP += bDof; 6896 6897 if (outValues) { 6898 /* get the point-to-point submatrix */ 6899 for (f = 0; f < numFields; f++) { 6900 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 6901 } 6902 } 6903 } 6904 else { 6905 newPoints[2 * newP] = b; 6906 newPoints[2 * newP + 1] = o; 6907 newP++; 6908 } 6909 } 6910 } else { 6911 for (p = 0; p < numPoints; p++) { 6912 PetscInt b = points[2*p]; 6913 PetscInt o = points[2*p+1]; 6914 PetscInt bDof = 0, bSecDof; 6915 6916 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6917 if (!bSecDof) { 6918 continue; 6919 } 6920 if (b >= aStart && b < aEnd) { 6921 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6922 } 6923 if (bDof) { 6924 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 6925 6926 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6927 ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 6928 6929 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 6930 for (q = 0; q < bDof; q++) { 6931 PetscInt a = anchors[bOff + q], aOff; 6932 6933 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6934 6935 newPoints[2*(newP + q)] = a; 6936 newPoints[2*(newP + q) + 1] = 0; 6937 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 6938 ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 6939 } 6940 newP += bDof; 6941 6942 /* get the point-to-point submatrix */ 6943 if (outValues) { 6944 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 6945 } 6946 } 6947 else { 6948 newPoints[2 * newP] = b; 6949 newPoints[2 * newP + 1] = o; 6950 newP++; 6951 } 6952 } 6953 } 6954 6955 if (outValues) { 6956 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 6957 ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr); 6958 /* multiply constraints on the right */ 6959 if (numFields) { 6960 for (f = 0; f < numFields; f++) { 6961 PetscInt oldOff = offsets[f]; 6962 6963 for (p = 0; p < numPoints; p++) { 6964 PetscInt cStart = newPointOffsets[f][p]; 6965 PetscInt b = points[2 * p]; 6966 PetscInt c, r, k; 6967 PetscInt dof; 6968 6969 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 6970 if (!dof) { 6971 continue; 6972 } 6973 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 6974 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 6975 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 6976 6977 for (r = 0; r < numIndices; r++) { 6978 for (c = 0; c < nCols; c++) { 6979 for (k = 0; k < dof; k++) { 6980 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 6981 } 6982 } 6983 } 6984 } 6985 else { 6986 /* copy this column as is */ 6987 for (r = 0; r < numIndices; r++) { 6988 for (c = 0; c < dof; c++) { 6989 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 6990 } 6991 } 6992 } 6993 oldOff += dof; 6994 } 6995 } 6996 } 6997 else { 6998 PetscInt oldOff = 0; 6999 for (p = 0; p < numPoints; p++) { 7000 PetscInt cStart = newPointOffsets[0][p]; 7001 PetscInt b = points[2 * p]; 7002 PetscInt c, r, k; 7003 PetscInt dof; 7004 7005 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7006 if (!dof) { 7007 continue; 7008 } 7009 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7010 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 7011 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7012 7013 for (r = 0; r < numIndices; r++) { 7014 for (c = 0; c < nCols; c++) { 7015 for (k = 0; k < dof; k++) { 7016 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7017 } 7018 } 7019 } 7020 } 7021 else { 7022 /* copy this column as is */ 7023 for (r = 0; r < numIndices; r++) { 7024 for (c = 0; c < dof; c++) { 7025 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7026 } 7027 } 7028 } 7029 oldOff += dof; 7030 } 7031 } 7032 7033 if (multiplyLeft) { 7034 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 7035 ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr); 7036 /* multiply constraints transpose on the left */ 7037 if (numFields) { 7038 for (f = 0; f < numFields; f++) { 7039 PetscInt oldOff = offsets[f]; 7040 7041 for (p = 0; p < numPoints; p++) { 7042 PetscInt rStart = newPointOffsets[f][p]; 7043 PetscInt b = points[2 * p]; 7044 PetscInt c, r, k; 7045 PetscInt dof; 7046 7047 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7048 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7049 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 7050 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7051 7052 for (r = 0; r < nRows; r++) { 7053 for (c = 0; c < newNumIndices; c++) { 7054 for (k = 0; k < dof; k++) { 7055 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7056 } 7057 } 7058 } 7059 } 7060 else { 7061 /* copy this row as is */ 7062 for (r = 0; r < dof; r++) { 7063 for (c = 0; c < newNumIndices; c++) { 7064 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7065 } 7066 } 7067 } 7068 oldOff += dof; 7069 } 7070 } 7071 } 7072 else { 7073 PetscInt oldOff = 0; 7074 7075 for (p = 0; p < numPoints; p++) { 7076 PetscInt rStart = newPointOffsets[0][p]; 7077 PetscInt b = points[2 * p]; 7078 PetscInt c, r, k; 7079 PetscInt dof; 7080 7081 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7082 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7083 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 7084 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7085 7086 for (r = 0; r < nRows; r++) { 7087 for (c = 0; c < newNumIndices; c++) { 7088 for (k = 0; k < dof; k++) { 7089 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7090 } 7091 } 7092 } 7093 } 7094 else { 7095 /* copy this row as is */ 7096 for (r = 0; r < dof; r++) { 7097 for (c = 0; c < newNumIndices; c++) { 7098 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7099 } 7100 } 7101 } 7102 oldOff += dof; 7103 } 7104 } 7105 7106 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7107 } 7108 else { 7109 newValues = tmpValues; 7110 } 7111 } 7112 7113 /* clean up */ 7114 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 7115 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 7116 7117 if (numFields) { 7118 for (f = 0; f < numFields; f++) { 7119 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 7120 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 7121 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 7122 } 7123 } 7124 else { 7125 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 7126 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 7127 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 7128 } 7129 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7130 7131 /* output */ 7132 if (outPoints) { 7133 *outPoints = newPoints; 7134 } 7135 else { 7136 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 7137 } 7138 if (outValues) { 7139 *outValues = newValues; 7140 } 7141 for (f = 0; f <= numFields; f++) { 7142 offsets[f] = newOffsets[f]; 7143 } 7144 PetscFunctionReturn(0); 7145 } 7146 7147 /*@C 7148 DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 7149 7150 Not collective 7151 7152 Input Parameters: 7153 + dm - The DM 7154 . section - The PetscSection describing the points (a local section) 7155 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7156 . point - The point defining the closure 7157 - useClPerm - Use the closure point permutation if available 7158 7159 Output Parameters: 7160 + numIndices - The number of dof indices in the closure of point with the input sections 7161 . indices - The dof indices 7162 . outOffsets - Array to write the field offsets into, or NULL 7163 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7164 7165 Notes: 7166 Must call DMPlexRestoreClosureIndices() to free allocated memory 7167 7168 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7169 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7170 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7171 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7172 indices (with the above semantics) are implied. 7173 7174 Level: advanced 7175 7176 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7177 @*/ 7178 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7179 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7180 { 7181 /* Closure ordering */ 7182 PetscSection clSection; 7183 IS clPoints; 7184 const PetscInt *clp; 7185 PetscInt *points; 7186 const PetscInt *clperm = NULL; 7187 /* Dof permutation and sign flips */ 7188 const PetscInt **perms[32] = {NULL}; 7189 const PetscScalar **flips[32] = {NULL}; 7190 PetscScalar *valCopy = NULL; 7191 /* Hanging node constraints */ 7192 PetscInt *pointsC = NULL; 7193 PetscScalar *valuesC = NULL; 7194 PetscInt NclC, NiC; 7195 7196 PetscInt *idx; 7197 PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 7198 PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 7199 PetscErrorCode ierr; 7200 7201 PetscFunctionBeginHot; 7202 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7203 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7204 PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7205 if (numIndices) PetscValidPointer(numIndices, 6); 7206 if (indices) PetscValidPointer(indices, 7); 7207 if (outOffsets) PetscValidPointer(outOffsets, 8); 7208 if (values) PetscValidPointer(values, 9); 7209 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 7210 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 7211 ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 7212 /* 1) Get points in closure */ 7213 ierr = DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7214 if (useClPerm) { 7215 PetscInt depth, clsize; 7216 ierr = DMPlexGetPointDepth(dm, point, &depth);CHKERRQ(ierr); 7217 for (clsize=0,p=0; p<Ncl; p++) { 7218 PetscInt dof; 7219 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 7220 clsize += dof; 7221 } 7222 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 7223 } 7224 /* 2) Get number of indices on these points and field offsets from section */ 7225 for (p = 0; p < Ncl*2; p += 2) { 7226 PetscInt dof, fdof; 7227 7228 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7229 for (f = 0; f < Nf; ++f) { 7230 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7231 offsets[f+1] += fdof; 7232 } 7233 Ni += dof; 7234 } 7235 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 7236 if (Nf && offsets[Nf] != Ni) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni); 7237 /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 7238 for (f = 0; f < PetscMax(1, Nf); ++f) { 7239 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7240 else {ierr = PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7241 /* may need to apply sign changes to the element matrix */ 7242 if (values && flips[f]) { 7243 PetscInt foffset = offsets[f]; 7244 7245 for (p = 0; p < Ncl; ++p) { 7246 PetscInt pnt = points[2*p], fdof; 7247 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 7248 7249 if (!Nf) {ierr = PetscSectionGetDof(section, pnt, &fdof);CHKERRQ(ierr);} 7250 else {ierr = PetscSectionGetFieldDof(section, pnt, f, &fdof);CHKERRQ(ierr);} 7251 if (flip) { 7252 PetscInt i, j, k; 7253 7254 if (!valCopy) { 7255 ierr = DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr); 7256 for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 7257 *values = valCopy; 7258 } 7259 for (i = 0; i < fdof; ++i) { 7260 PetscScalar fval = flip[i]; 7261 7262 for (k = 0; k < Ni; ++k) { 7263 valCopy[Ni * (foffset + i) + k] *= fval; 7264 valCopy[Ni * k + (foffset + i)] *= fval; 7265 } 7266 } 7267 } 7268 foffset += fdof; 7269 } 7270 } 7271 } 7272 /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 7273 ierr = DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 7274 if (NclC) { 7275 if (valCopy) {ierr = DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);} 7276 for (f = 0; f < PetscMax(1, Nf); ++f) { 7277 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7278 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7279 } 7280 for (f = 0; f < PetscMax(1, Nf); ++f) { 7281 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7282 else {ierr = PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7283 } 7284 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7285 Ncl = NclC; 7286 Ni = NiC; 7287 points = pointsC; 7288 if (values) *values = valuesC; 7289 } 7290 /* 5) Calculate indices */ 7291 ierr = DMGetWorkArray(dm, Ni, MPIU_INT, &idx);CHKERRQ(ierr); 7292 if (Nf) { 7293 PetscInt idxOff; 7294 PetscBool useFieldOffsets; 7295 7296 if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 7297 ierr = PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets);CHKERRQ(ierr); 7298 if (useFieldOffsets) { 7299 for (p = 0; p < Ncl; ++p) { 7300 const PetscInt pnt = points[p*2]; 7301 7302 ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx);CHKERRQ(ierr); 7303 } 7304 } else { 7305 for (p = 0; p < Ncl; ++p) { 7306 const PetscInt pnt = points[p*2]; 7307 7308 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7309 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7310 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 7311 * global section. */ 7312 ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx);CHKERRQ(ierr); 7313 } 7314 } 7315 } else { 7316 PetscInt off = 0, idxOff; 7317 7318 for (p = 0; p < Ncl; ++p) { 7319 const PetscInt pnt = points[p*2]; 7320 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 7321 7322 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7323 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7324 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 7325 ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx);CHKERRQ(ierr); 7326 } 7327 } 7328 /* 6) Cleanup */ 7329 for (f = 0; f < PetscMax(1, Nf); ++f) { 7330 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7331 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7332 } 7333 if (NclC) { 7334 ierr = DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC);CHKERRQ(ierr); 7335 } else { 7336 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7337 } 7338 7339 if (numIndices) *numIndices = Ni; 7340 if (indices) *indices = idx; 7341 PetscFunctionReturn(0); 7342 } 7343 7344 /*@C 7345 DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 7346 7347 Not collective 7348 7349 Input Parameters: 7350 + dm - The DM 7351 . section - The PetscSection describing the points (a local section) 7352 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7353 . point - The point defining the closure 7354 - useClPerm - Use the closure point permutation if available 7355 7356 Output Parameters: 7357 + numIndices - The number of dof indices in the closure of point with the input sections 7358 . indices - The dof indices 7359 . outOffsets - Array to write the field offsets into, or NULL 7360 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7361 7362 Notes: 7363 If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 7364 7365 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7366 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7367 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7368 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7369 indices (with the above semantics) are implied. 7370 7371 Level: advanced 7372 7373 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7374 @*/ 7375 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7376 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7377 { 7378 PetscErrorCode ierr; 7379 7380 PetscFunctionBegin; 7381 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7382 PetscValidPointer(indices, 7); 7383 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 7384 PetscFunctionReturn(0); 7385 } 7386 7387 /*@C 7388 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 7389 7390 Not collective 7391 7392 Input Parameters: 7393 + dm - The DM 7394 . section - The section describing the layout in v, or NULL to use the default section 7395 . globalSection - The section describing the layout in v, or NULL to use the default global section 7396 . A - The matrix 7397 . point - The point in the DM 7398 . values - The array of values 7399 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7400 7401 Fortran Notes: 7402 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 7403 7404 Level: intermediate 7405 7406 .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7407 @*/ 7408 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7409 { 7410 DM_Plex *mesh = (DM_Plex*) dm->data; 7411 PetscInt *indices; 7412 PetscInt numIndices; 7413 const PetscScalar *valuesOrig = values; 7414 PetscErrorCode ierr; 7415 7416 PetscFunctionBegin; 7417 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7418 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 7419 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7420 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 7421 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 7422 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7423 7424 ierr = DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7425 7426 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 7427 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7428 if (ierr) { 7429 PetscMPIInt rank; 7430 PetscErrorCode ierr2; 7431 7432 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7433 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7434 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 7435 ierr2 = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7436 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7437 CHKERRQ(ierr); 7438 } 7439 if (mesh->printFEM > 1) { 7440 PetscInt i; 7441 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 7442 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 7443 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7444 } 7445 7446 ierr = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7447 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7448 PetscFunctionReturn(0); 7449 } 7450 7451 /*@C 7452 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 7453 7454 Not collective 7455 7456 Input Parameters: 7457 + dmRow - The DM for the row fields 7458 . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 7459 . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 7460 . dmCol - The DM for the column fields 7461 . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 7462 . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 7463 . A - The matrix 7464 . point - The point in the DMs 7465 . values - The array of values 7466 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7467 7468 Level: intermediate 7469 7470 .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7471 @*/ 7472 PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7473 { 7474 DM_Plex *mesh = (DM_Plex*) dmRow->data; 7475 PetscInt *indicesRow, *indicesCol; 7476 PetscInt numIndicesRow, numIndicesCol; 7477 const PetscScalar *valuesOrig = values; 7478 PetscErrorCode ierr; 7479 7480 PetscFunctionBegin; 7481 PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 7482 if (!sectionRow) {ierr = DMGetLocalSection(dmRow, §ionRow);CHKERRQ(ierr);} 7483 PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 7484 if (!globalSectionRow) {ierr = DMGetGlobalSection(dmRow, &globalSectionRow);CHKERRQ(ierr);} 7485 PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 7486 PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 7487 if (!sectionCol) {ierr = DMGetLocalSection(dmCol, §ionCol);CHKERRQ(ierr);} 7488 PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 7489 if (!globalSectionCol) {ierr = DMGetGlobalSection(dmCol, &globalSectionCol);CHKERRQ(ierr);} 7490 PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 7491 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7492 7493 ierr = DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7494 ierr = DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7495 7496 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr);} 7497 ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 7498 if (ierr) { 7499 PetscMPIInt rank; 7500 PetscErrorCode ierr2; 7501 7502 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7503 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7504 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr2); 7505 ierr2 = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7506 ierr2 = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7507 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7508 CHKERRQ(ierr); 7509 } 7510 7511 ierr = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7512 ierr = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7513 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7514 PetscFunctionReturn(0); 7515 } 7516 7517 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7518 { 7519 DM_Plex *mesh = (DM_Plex*) dmf->data; 7520 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7521 PetscInt *cpoints = NULL; 7522 PetscInt *findices, *cindices; 7523 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7524 PetscInt foffsets[32], coffsets[32]; 7525 DMPolytopeType ct; 7526 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7527 PetscErrorCode ierr; 7528 7529 PetscFunctionBegin; 7530 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7531 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7532 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7533 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7534 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7535 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7536 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7537 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7538 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7539 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7540 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7541 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7542 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7543 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7544 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7545 /* Column indices */ 7546 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7547 maxFPoints = numCPoints; 7548 /* Compress out points not in the section */ 7549 /* TODO: Squeeze out points with 0 dof as well */ 7550 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7551 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7552 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7553 cpoints[q*2] = cpoints[p]; 7554 cpoints[q*2+1] = cpoints[p+1]; 7555 ++q; 7556 } 7557 } 7558 numCPoints = q; 7559 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7560 PetscInt fdof; 7561 7562 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7563 if (!dof) continue; 7564 for (f = 0; f < numFields; ++f) { 7565 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7566 coffsets[f+1] += fdof; 7567 } 7568 numCIndices += dof; 7569 } 7570 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7571 /* Row indices */ 7572 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7573 { 7574 DMPlexCellRefiner cr; 7575 ierr = DMPlexCellRefinerCreate(dmc, &cr);CHKERRQ(ierr); 7576 ierr = DMPlexCellRefinerGetAffineTransforms(cr, ct, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 7577 ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 7578 } 7579 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7580 for (r = 0, q = 0; r < numSubcells; ++r) { 7581 /* TODO Map from coarse to fine cells */ 7582 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7583 /* Compress out points not in the section */ 7584 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7585 for (p = 0; p < numFPoints*2; p += 2) { 7586 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7587 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7588 if (!dof) continue; 7589 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7590 if (s < q) continue; 7591 ftotpoints[q*2] = fpoints[p]; 7592 ftotpoints[q*2+1] = fpoints[p+1]; 7593 ++q; 7594 } 7595 } 7596 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7597 } 7598 numFPoints = q; 7599 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7600 PetscInt fdof; 7601 7602 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7603 if (!dof) continue; 7604 for (f = 0; f < numFields; ++f) { 7605 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7606 foffsets[f+1] += fdof; 7607 } 7608 numFIndices += dof; 7609 } 7610 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7611 7612 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7613 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7614 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7615 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7616 if (numFields) { 7617 const PetscInt **permsF[32] = {NULL}; 7618 const PetscInt **permsC[32] = {NULL}; 7619 7620 for (f = 0; f < numFields; f++) { 7621 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7622 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7623 } 7624 for (p = 0; p < numFPoints; p++) { 7625 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7626 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7627 } 7628 for (p = 0; p < numCPoints; p++) { 7629 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7630 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7631 } 7632 for (f = 0; f < numFields; f++) { 7633 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7634 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7635 } 7636 } else { 7637 const PetscInt **permsF = NULL; 7638 const PetscInt **permsC = NULL; 7639 7640 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7641 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7642 for (p = 0, off = 0; p < numFPoints; p++) { 7643 const PetscInt *perm = permsF ? permsF[p] : NULL; 7644 7645 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7646 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7647 } 7648 for (p = 0, off = 0; p < numCPoints; p++) { 7649 const PetscInt *perm = permsC ? permsC[p] : NULL; 7650 7651 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7652 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7653 } 7654 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7655 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7656 } 7657 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 7658 /* TODO: flips */ 7659 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7660 if (ierr) { 7661 PetscMPIInt rank; 7662 PetscErrorCode ierr2; 7663 7664 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7665 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7666 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 7667 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 7668 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 7669 CHKERRQ(ierr); 7670 } 7671 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7672 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7673 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7674 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7675 PetscFunctionReturn(0); 7676 } 7677 7678 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 7679 { 7680 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7681 PetscInt *cpoints = NULL; 7682 PetscInt foffsets[32], coffsets[32]; 7683 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7684 DMPolytopeType ct; 7685 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7686 PetscErrorCode ierr; 7687 7688 PetscFunctionBegin; 7689 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7690 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7691 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7692 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7693 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7694 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7695 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7696 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7697 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7698 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7699 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7700 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7701 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7702 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7703 /* Column indices */ 7704 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7705 maxFPoints = numCPoints; 7706 /* Compress out points not in the section */ 7707 /* TODO: Squeeze out points with 0 dof as well */ 7708 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7709 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7710 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7711 cpoints[q*2] = cpoints[p]; 7712 cpoints[q*2+1] = cpoints[p+1]; 7713 ++q; 7714 } 7715 } 7716 numCPoints = q; 7717 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7718 PetscInt fdof; 7719 7720 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7721 if (!dof) continue; 7722 for (f = 0; f < numFields; ++f) { 7723 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7724 coffsets[f+1] += fdof; 7725 } 7726 numCIndices += dof; 7727 } 7728 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7729 /* Row indices */ 7730 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7731 { 7732 DMPlexCellRefiner cr; 7733 ierr = DMPlexCellRefinerCreate(dmc, &cr);CHKERRQ(ierr); 7734 ierr = DMPlexCellRefinerGetAffineTransforms(cr, ct, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 7735 ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 7736 } 7737 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7738 for (r = 0, q = 0; r < numSubcells; ++r) { 7739 /* TODO Map from coarse to fine cells */ 7740 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7741 /* Compress out points not in the section */ 7742 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7743 for (p = 0; p < numFPoints*2; p += 2) { 7744 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7745 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7746 if (!dof) continue; 7747 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7748 if (s < q) continue; 7749 ftotpoints[q*2] = fpoints[p]; 7750 ftotpoints[q*2+1] = fpoints[p+1]; 7751 ++q; 7752 } 7753 } 7754 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7755 } 7756 numFPoints = q; 7757 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7758 PetscInt fdof; 7759 7760 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7761 if (!dof) continue; 7762 for (f = 0; f < numFields; ++f) { 7763 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7764 foffsets[f+1] += fdof; 7765 } 7766 numFIndices += dof; 7767 } 7768 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7769 7770 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7771 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7772 if (numFields) { 7773 const PetscInt **permsF[32] = {NULL}; 7774 const PetscInt **permsC[32] = {NULL}; 7775 7776 for (f = 0; f < numFields; f++) { 7777 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7778 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7779 } 7780 for (p = 0; p < numFPoints; p++) { 7781 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7782 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7783 } 7784 for (p = 0; p < numCPoints; p++) { 7785 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7786 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7787 } 7788 for (f = 0; f < numFields; f++) { 7789 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7790 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7791 } 7792 } else { 7793 const PetscInt **permsF = NULL; 7794 const PetscInt **permsC = NULL; 7795 7796 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7797 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7798 for (p = 0, off = 0; p < numFPoints; p++) { 7799 const PetscInt *perm = permsF ? permsF[p] : NULL; 7800 7801 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7802 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7803 } 7804 for (p = 0, off = 0; p < numCPoints; p++) { 7805 const PetscInt *perm = permsC ? permsC[p] : NULL; 7806 7807 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7808 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7809 } 7810 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7811 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7812 } 7813 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7814 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7815 PetscFunctionReturn(0); 7816 } 7817 7818 /*@C 7819 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 7820 7821 Input Parameter: 7822 . dm - The DMPlex object 7823 7824 Output Parameter: 7825 . cellHeight - The height of a cell 7826 7827 Level: developer 7828 7829 .seealso DMPlexSetVTKCellHeight() 7830 @*/ 7831 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7832 { 7833 DM_Plex *mesh = (DM_Plex*) dm->data; 7834 7835 PetscFunctionBegin; 7836 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7837 PetscValidPointer(cellHeight, 2); 7838 *cellHeight = mesh->vtkCellHeight; 7839 PetscFunctionReturn(0); 7840 } 7841 7842 /*@C 7843 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 7844 7845 Input Parameters: 7846 + dm - The DMPlex object 7847 - cellHeight - The height of a cell 7848 7849 Level: developer 7850 7851 .seealso DMPlexGetVTKCellHeight() 7852 @*/ 7853 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7854 { 7855 DM_Plex *mesh = (DM_Plex*) dm->data; 7856 7857 PetscFunctionBegin; 7858 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7859 mesh->vtkCellHeight = cellHeight; 7860 PetscFunctionReturn(0); 7861 } 7862 7863 /*@ 7864 DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 7865 7866 Input Parameter: 7867 . dm - The DMPlex object 7868 7869 Output Parameters: 7870 + gcStart - The first ghost cell, or NULL 7871 - gcEnd - The upper bound on ghost cells, or NULL 7872 7873 Level: advanced 7874 7875 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 7876 @*/ 7877 PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 7878 { 7879 DMLabel ctLabel; 7880 PetscErrorCode ierr; 7881 7882 PetscFunctionBegin; 7883 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7884 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 7885 ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr); 7886 PetscFunctionReturn(0); 7887 } 7888 7889 /* We can easily have a form that takes an IS instead */ 7890 PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 7891 { 7892 PetscSection section, globalSection; 7893 PetscInt *numbers, p; 7894 PetscErrorCode ierr; 7895 7896 PetscFunctionBegin; 7897 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7898 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 7899 for (p = pStart; p < pEnd; ++p) { 7900 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 7901 } 7902 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 7903 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7904 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 7905 for (p = pStart; p < pEnd; ++p) { 7906 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 7907 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 7908 else numbers[p-pStart] += shift; 7909 } 7910 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 7911 if (globalSize) { 7912 PetscLayout layout; 7913 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 7914 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 7915 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 7916 } 7917 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7918 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 7919 PetscFunctionReturn(0); 7920 } 7921 7922 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 7923 { 7924 PetscInt cellHeight, cStart, cEnd; 7925 PetscErrorCode ierr; 7926 7927 PetscFunctionBegin; 7928 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 7929 if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 7930 else {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 7931 ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 7932 PetscFunctionReturn(0); 7933 } 7934 7935 /*@ 7936 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 7937 7938 Input Parameter: 7939 . dm - The DMPlex object 7940 7941 Output Parameter: 7942 . globalCellNumbers - Global cell numbers for all cells on this process 7943 7944 Level: developer 7945 7946 .seealso DMPlexGetVertexNumbering() 7947 @*/ 7948 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 7949 { 7950 DM_Plex *mesh = (DM_Plex*) dm->data; 7951 PetscErrorCode ierr; 7952 7953 PetscFunctionBegin; 7954 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7955 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 7956 *globalCellNumbers = mesh->globalCellNumbers; 7957 PetscFunctionReturn(0); 7958 } 7959 7960 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 7961 { 7962 PetscInt vStart, vEnd; 7963 PetscErrorCode ierr; 7964 7965 PetscFunctionBegin; 7966 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7967 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7968 ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 7969 PetscFunctionReturn(0); 7970 } 7971 7972 /*@ 7973 DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 7974 7975 Input Parameter: 7976 . dm - The DMPlex object 7977 7978 Output Parameter: 7979 . globalVertexNumbers - Global vertex numbers for all vertices on this process 7980 7981 Level: developer 7982 7983 .seealso DMPlexGetCellNumbering() 7984 @*/ 7985 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 7986 { 7987 DM_Plex *mesh = (DM_Plex*) dm->data; 7988 PetscErrorCode ierr; 7989 7990 PetscFunctionBegin; 7991 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7992 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 7993 *globalVertexNumbers = mesh->globalVertexNumbers; 7994 PetscFunctionReturn(0); 7995 } 7996 7997 /*@ 7998 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 7999 8000 Input Parameter: 8001 . dm - The DMPlex object 8002 8003 Output Parameter: 8004 . globalPointNumbers - Global numbers for all points on this process 8005 8006 Level: developer 8007 8008 .seealso DMPlexGetCellNumbering() 8009 @*/ 8010 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8011 { 8012 IS nums[4]; 8013 PetscInt depths[4], gdepths[4], starts[4]; 8014 PetscInt depth, d, shift = 0; 8015 PetscErrorCode ierr; 8016 8017 PetscFunctionBegin; 8018 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8019 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8020 /* For unstratified meshes use dim instead of depth */ 8021 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 8022 for (d = 0; d <= depth; ++d) { 8023 PetscInt end; 8024 8025 depths[d] = depth-d; 8026 ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 8027 if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 8028 } 8029 ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 8030 ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 8031 for (d = 0; d <= depth; ++d) { 8032 if (starts[d] >= 0 && depths[d] != gdepths[d]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 8033 } 8034 for (d = 0; d <= depth; ++d) { 8035 PetscInt pStart, pEnd, gsize; 8036 8037 ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 8038 ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 8039 shift += gsize; 8040 } 8041 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 8042 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 8043 PetscFunctionReturn(0); 8044 } 8045 8046 /*@ 8047 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 8048 8049 Input Parameter: 8050 . dm - The DMPlex object 8051 8052 Output Parameter: 8053 . ranks - The rank field 8054 8055 Options Database Keys: 8056 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 8057 8058 Level: intermediate 8059 8060 .seealso: DMView() 8061 @*/ 8062 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8063 { 8064 DM rdm; 8065 PetscFE fe; 8066 PetscScalar *r; 8067 PetscMPIInt rank; 8068 DMPolytopeType ct; 8069 PetscInt dim, cStart, cEnd, c; 8070 PetscBool simplex; 8071 PetscErrorCode ierr; 8072 8073 PetscFunctionBeginUser; 8074 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8075 PetscValidPointer(ranks, 2); 8076 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 8077 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8078 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8079 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8080 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 8081 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 8082 ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 8083 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 8084 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8085 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8086 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8087 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 8088 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 8089 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 8090 for (c = cStart; c < cEnd; ++c) { 8091 PetscScalar *lr; 8092 8093 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 8094 if (lr) *lr = rank; 8095 } 8096 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 8097 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8098 PetscFunctionReturn(0); 8099 } 8100 8101 /*@ 8102 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 8103 8104 Input Parameters: 8105 + dm - The DMPlex 8106 - label - The DMLabel 8107 8108 Output Parameter: 8109 . val - The label value field 8110 8111 Options Database Keys: 8112 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 8113 8114 Level: intermediate 8115 8116 .seealso: DMView() 8117 @*/ 8118 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8119 { 8120 DM rdm; 8121 PetscFE fe; 8122 PetscScalar *v; 8123 PetscInt dim, cStart, cEnd, c; 8124 PetscErrorCode ierr; 8125 8126 PetscFunctionBeginUser; 8127 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8128 PetscValidPointer(label, 2); 8129 PetscValidPointer(val, 3); 8130 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8131 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8132 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 8133 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 8134 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8135 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8136 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8137 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8138 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 8139 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 8140 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 8141 for (c = cStart; c < cEnd; ++c) { 8142 PetscScalar *lv; 8143 PetscInt cval; 8144 8145 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 8146 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 8147 *lv = cval; 8148 } 8149 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 8150 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8151 PetscFunctionReturn(0); 8152 } 8153 8154 /*@ 8155 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8156 8157 Input Parameter: 8158 . dm - The DMPlex object 8159 8160 Notes: 8161 This is a useful diagnostic when creating meshes programmatically. 8162 8163 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8164 8165 Level: developer 8166 8167 .seealso: DMCreate(), DMSetFromOptions() 8168 @*/ 8169 PetscErrorCode DMPlexCheckSymmetry(DM dm) 8170 { 8171 PetscSection coneSection, supportSection; 8172 const PetscInt *cone, *support; 8173 PetscInt coneSize, c, supportSize, s; 8174 PetscInt pStart, pEnd, p, pp, csize, ssize; 8175 PetscBool storagecheck = PETSC_TRUE; 8176 PetscErrorCode ierr; 8177 8178 PetscFunctionBegin; 8179 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8180 ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr); 8181 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 8182 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 8183 /* Check that point p is found in the support of its cone points, and vice versa */ 8184 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8185 for (p = pStart; p < pEnd; ++p) { 8186 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8187 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8188 for (c = 0; c < coneSize; ++c) { 8189 PetscBool dup = PETSC_FALSE; 8190 PetscInt d; 8191 for (d = c-1; d >= 0; --d) { 8192 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 8193 } 8194 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 8195 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 8196 for (s = 0; s < supportSize; ++s) { 8197 if (support[s] == p) break; 8198 } 8199 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 8200 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 8201 for (s = 0; s < coneSize; ++s) { 8202 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 8203 } 8204 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8205 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 8206 for (s = 0; s < supportSize; ++s) { 8207 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 8208 } 8209 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8210 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 8211 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 8212 } 8213 } 8214 ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 8215 if (p != pp) { storagecheck = PETSC_FALSE; continue; } 8216 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 8217 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 8218 for (s = 0; s < supportSize; ++s) { 8219 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 8220 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 8221 for (c = 0; c < coneSize; ++c) { 8222 ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 8223 if (cone[c] != pp) { c = 0; break; } 8224 if (cone[c] == p) break; 8225 } 8226 if (c >= coneSize) { 8227 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 8228 for (c = 0; c < supportSize; ++c) { 8229 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 8230 } 8231 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8232 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 8233 for (c = 0; c < coneSize; ++c) { 8234 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 8235 } 8236 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8237 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 8238 } 8239 } 8240 } 8241 if (storagecheck) { 8242 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 8243 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 8244 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 8245 } 8246 PetscFunctionReturn(0); 8247 } 8248 8249 /* 8250 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. 8251 */ 8252 static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8253 { 8254 DMPolytopeType cct; 8255 PetscInt ptpoints[4]; 8256 const PetscInt *cone, *ccone, *ptcone; 8257 PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8258 PetscErrorCode ierr; 8259 8260 PetscFunctionBegin; 8261 *unsplit = 0; 8262 switch (ct) { 8263 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8264 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8265 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8266 for (cp = 0; cp < coneSize; ++cp) { 8267 ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr); 8268 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8269 } 8270 break; 8271 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8272 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8273 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8274 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8275 for (cp = 0; cp < coneSize; ++cp) { 8276 ierr = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr); 8277 ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr); 8278 for (ccp = 0; ccp < cconeSize; ++ccp) { 8279 ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr); 8280 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8281 PetscInt p; 8282 for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8283 if (p == npt) ptpoints[npt++] = ccone[ccp]; 8284 } 8285 } 8286 } 8287 break; 8288 default: break; 8289 } 8290 for (pt = 0; pt < npt; ++pt) { 8291 ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr); 8292 if (ptcone[0] == ptcone[1]) ++(*unsplit); 8293 } 8294 PetscFunctionReturn(0); 8295 } 8296 8297 /*@ 8298 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8299 8300 Input Parameters: 8301 + dm - The DMPlex object 8302 - cellHeight - Normally 0 8303 8304 Notes: 8305 This is a useful diagnostic when creating meshes programmatically. 8306 Currently applicable only to homogeneous simplex or tensor meshes. 8307 8308 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8309 8310 Level: developer 8311 8312 .seealso: DMCreate(), DMSetFromOptions() 8313 @*/ 8314 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8315 { 8316 DMPlexInterpolatedFlag interp; 8317 DMPolytopeType ct; 8318 PetscInt vStart, vEnd, cStart, cEnd, c; 8319 PetscErrorCode ierr; 8320 8321 PetscFunctionBegin; 8322 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8323 ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr); 8324 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8325 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8326 for (c = cStart; c < cEnd; ++c) { 8327 PetscInt *closure = NULL; 8328 PetscInt coneSize, closureSize, cl, Nv = 0; 8329 8330 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8331 if ((PetscInt) ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c); 8332 if (ct == DM_POLYTOPE_UNKNOWN) continue; 8333 if (interp == DMPLEX_INTERPOLATED_FULL) { 8334 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8335 if (coneSize != DMPolytopeTypeGetConeSize(ct)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has cone size %D != %D", c, DMPolytopeTypes[ct], coneSize, DMPolytopeTypeGetConeSize(ct)); 8336 } 8337 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8338 for (cl = 0; cl < closureSize*2; cl += 2) { 8339 const PetscInt p = closure[cl]; 8340 if ((p >= vStart) && (p < vEnd)) ++Nv; 8341 } 8342 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8343 /* Special Case: Tensor faces with identified vertices */ 8344 if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8345 PetscInt unsplit; 8346 8347 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8348 if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 8349 } 8350 if (Nv != DMPolytopeTypeGetNumVertices(ct)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has %D vertices != %D", c, DMPolytopeTypes[ct], Nv, DMPolytopeTypeGetNumVertices(ct)); 8351 } 8352 PetscFunctionReturn(0); 8353 } 8354 8355 /*@ 8356 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 8357 8358 Not Collective 8359 8360 Input Parameters: 8361 + dm - The DMPlex object 8362 - cellHeight - Normally 0 8363 8364 Notes: 8365 This is a useful diagnostic when creating meshes programmatically. 8366 This routine is only relevant for meshes that are fully interpolated across all ranks. 8367 It will error out if a partially interpolated mesh is given on some rank. 8368 It will do nothing for locally uninterpolated mesh (as there is nothing to check). 8369 8370 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8371 8372 Level: developer 8373 8374 .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 8375 @*/ 8376 PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 8377 { 8378 PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8379 PetscErrorCode ierr; 8380 DMPlexInterpolatedFlag interpEnum; 8381 8382 PetscFunctionBegin; 8383 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8384 ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr); 8385 if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 8386 if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 8387 PetscMPIInt rank; 8388 MPI_Comm comm; 8389 8390 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8391 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8392 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 8393 } 8394 8395 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8396 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8397 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8398 for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 8399 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 8400 for (c = cStart; c < cEnd; ++c) { 8401 const PetscInt *cone, *ornt, *faceSizes, *faces; 8402 const DMPolytopeType *faceTypes; 8403 DMPolytopeType ct; 8404 PetscInt numFaces, coneSize, f; 8405 PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 8406 8407 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8408 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8409 if (unsplit) continue; 8410 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8411 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8412 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 8413 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8414 for (cl = 0; cl < closureSize*2; cl += 2) { 8415 const PetscInt p = closure[cl]; 8416 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 8417 } 8418 ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8419 if (coneSize != numFaces) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has %D faces but should have %D", c, DMPolytopeTypes[ct], coneSize, numFaces); 8420 for (f = 0; f < numFaces; ++f) { 8421 DMPolytopeType fct; 8422 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 8423 8424 ierr = DMPlexGetCellType(dm, cone[f], &fct);CHKERRQ(ierr); 8425 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8426 for (cl = 0; cl < fclosureSize*2; cl += 2) { 8427 const PetscInt p = fclosure[cl]; 8428 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 8429 } 8430 if (fnumCorners != faceSizes[f]) SETERRQ7(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]); 8431 for (v = 0; v < fnumCorners; ++v) { 8432 if (fclosure[v] != faces[fOff+v]) SETERRQ8(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D of type %s (cone idx %d) of cell %D of type %s vertex %D, %D != %D", cone[f], DMPolytopeTypes[fct], f, c, DMPolytopeTypes[ct], v, fclosure[v], faces[fOff+v]); 8433 } 8434 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8435 fOff += faceSizes[f]; 8436 } 8437 ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8438 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8439 } 8440 } 8441 PetscFunctionReturn(0); 8442 } 8443 8444 /*@ 8445 DMPlexCheckGeometry - Check the geometry of mesh cells 8446 8447 Input Parameter: 8448 . dm - The DMPlex object 8449 8450 Notes: 8451 This is a useful diagnostic when creating meshes programmatically. 8452 8453 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8454 8455 Level: developer 8456 8457 .seealso: DMCreate(), DMSetFromOptions() 8458 @*/ 8459 PetscErrorCode DMPlexCheckGeometry(DM dm) 8460 { 8461 Vec coordinates; 8462 PetscReal detJ, J[9], refVol = 1.0; 8463 PetscReal vol; 8464 PetscBool periodic; 8465 PetscInt dim, depth, dE, d, cStart, cEnd, c; 8466 PetscErrorCode ierr; 8467 8468 PetscFunctionBegin; 8469 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8470 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 8471 if (dim != dE) PetscFunctionReturn(0); 8472 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8473 ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr); 8474 for (d = 0; d < dim; ++d) refVol *= 2.0; 8475 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8476 /* Make sure local coordinates are created, because that step is collective */ 8477 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8478 for (c = cStart; c < cEnd; ++c) { 8479 DMPolytopeType ct; 8480 PetscInt unsplit; 8481 PetscBool ignoreZeroVol = PETSC_FALSE; 8482 8483 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8484 switch (ct) { 8485 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8486 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8487 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8488 ignoreZeroVol = PETSC_TRUE; break; 8489 default: break; 8490 } 8491 switch (ct) { 8492 case DM_POLYTOPE_TRI_PRISM: 8493 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8494 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8495 case DM_POLYTOPE_PYRAMID: 8496 continue; 8497 default: break; 8498 } 8499 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8500 if (unsplit) continue; 8501 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 8502 if (detJ < -PETSC_SMALL || (detJ <= 0.0 && !ignoreZeroVol)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D of type %s is inverted, |J| = %g", c, DMPolytopeTypes[ct], (double) detJ); 8503 ierr = PetscInfo2(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 8504 if (depth > 1 && !periodic) { 8505 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 8506 if (vol < -PETSC_SMALL || (vol <= 0.0 && !ignoreZeroVol)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D of type %s is inverted, vol = %g", c, DMPolytopeTypes[ct], (double) vol); 8507 ierr = PetscInfo2(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 8508 } 8509 } 8510 PetscFunctionReturn(0); 8511 } 8512 8513 /*@ 8514 DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 8515 8516 Input Parameters: 8517 . dm - The DMPlex object 8518 8519 Notes: 8520 This is mainly intended for debugging/testing purposes. 8521 It currently checks only meshes with no partition overlapping. 8522 8523 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8524 8525 Level: developer 8526 8527 .seealso: DMGetPointSF(), DMSetFromOptions() 8528 @*/ 8529 PetscErrorCode DMPlexCheckPointSF(DM dm) 8530 { 8531 PetscSF pointSF; 8532 PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 8533 const PetscInt *locals, *rootdegree; 8534 PetscBool distributed; 8535 PetscErrorCode ierr; 8536 8537 PetscFunctionBegin; 8538 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8539 ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr); 8540 ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 8541 if (!distributed) PetscFunctionReturn(0); 8542 ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 8543 if (overlap) { 8544 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping");CHKERRQ(ierr); 8545 PetscFunctionReturn(0); 8546 } 8547 if (!pointSF) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 8548 ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr); 8549 if (nroots < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 8550 ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 8551 ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 8552 8553 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 8554 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8555 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8556 for (l = 0; l < nleaves; ++l) { 8557 const PetscInt point = locals[l]; 8558 8559 if (point >= cStart && point < cEnd) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 8560 } 8561 8562 /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 8563 for (l = 0; l < nleaves; ++l) { 8564 const PetscInt point = locals[l]; 8565 const PetscInt *cone; 8566 PetscInt coneSize, c, idx; 8567 8568 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 8569 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 8570 for (c = 0; c < coneSize; ++c) { 8571 if (!rootdegree[cone[c]]) { 8572 ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr); 8573 if (idx < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 8574 } 8575 } 8576 } 8577 PetscFunctionReturn(0); 8578 } 8579 8580 typedef struct cell_stats 8581 { 8582 PetscReal min, max, sum, squaresum; 8583 PetscInt count; 8584 } cell_stats_t; 8585 8586 static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8587 { 8588 PetscInt i, N = *len; 8589 8590 for (i = 0; i < N; i++) { 8591 cell_stats_t *A = (cell_stats_t *) a; 8592 cell_stats_t *B = (cell_stats_t *) b; 8593 8594 B->min = PetscMin(A->min,B->min); 8595 B->max = PetscMax(A->max,B->max); 8596 B->sum += A->sum; 8597 B->squaresum += A->squaresum; 8598 B->count += A->count; 8599 } 8600 } 8601 8602 /*@ 8603 DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8604 8605 Collective on dm 8606 8607 Input Parameters: 8608 + dm - The DMPlex object 8609 . output - If true, statistics will be displayed on stdout 8610 - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8611 8612 Notes: 8613 This is mainly intended for debugging/testing purposes. 8614 8615 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8616 8617 Level: developer 8618 8619 .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality() 8620 @*/ 8621 PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8622 { 8623 DM dmCoarse; 8624 cell_stats_t stats, globalStats; 8625 MPI_Comm comm = PetscObjectComm((PetscObject)dm); 8626 PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 8627 PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8628 PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 8629 PetscMPIInt rank,size; 8630 PetscErrorCode ierr; 8631 8632 PetscFunctionBegin; 8633 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8634 stats.min = PETSC_MAX_REAL; 8635 stats.max = PETSC_MIN_REAL; 8636 stats.sum = stats.squaresum = 0.; 8637 stats.count = 0; 8638 8639 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 8640 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8641 ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr); 8642 ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr); 8643 ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 8644 ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); 8645 for (c = cStart; c < cEnd; c++) { 8646 PetscInt i; 8647 PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8648 8649 ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 8650 if (detJ < 0.0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 8651 for (i = 0; i < PetscSqr(cdim); ++i) { 8652 frobJ += J[i] * J[i]; 8653 frobInvJ += invJ[i] * invJ[i]; 8654 } 8655 cond2 = frobJ * frobInvJ; 8656 cond = PetscSqrtReal(cond2); 8657 8658 stats.min = PetscMin(stats.min,cond); 8659 stats.max = PetscMax(stats.max,cond); 8660 stats.sum += cond; 8661 stats.squaresum += cond2; 8662 stats.count++; 8663 if (output && cond > limit) { 8664 PetscSection coordSection; 8665 Vec coordsLocal; 8666 PetscScalar *coords = NULL; 8667 PetscInt Nv, d, clSize, cl, *closure = NULL; 8668 8669 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8670 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8671 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8672 ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr); 8673 for (i = 0; i < Nv/cdim; ++i) { 8674 ierr = PetscSynchronizedPrintf(comm, " Vertex %D: (", i);CHKERRQ(ierr); 8675 for (d = 0; d < cdim; ++d) { 8676 if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);} 8677 ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr); 8678 } 8679 ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr); 8680 } 8681 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8682 for (cl = 0; cl < clSize*2; cl += 2) { 8683 const PetscInt edge = closure[cl]; 8684 8685 if ((edge >= eStart) && (edge < eEnd)) { 8686 PetscReal len; 8687 8688 ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr); 8689 ierr = PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr); 8690 } 8691 } 8692 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8693 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8694 } 8695 } 8696 if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 8697 8698 if (size > 1) { 8699 PetscMPIInt blockLengths[2] = {4,1}; 8700 MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8701 MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8702 MPI_Op statReduce; 8703 8704 ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRMPI(ierr); 8705 ierr = MPI_Type_commit(&statType);CHKERRMPI(ierr); 8706 ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRMPI(ierr); 8707 ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRMPI(ierr); 8708 ierr = MPI_Op_free(&statReduce);CHKERRMPI(ierr); 8709 ierr = MPI_Type_free(&statType);CHKERRMPI(ierr); 8710 } else { 8711 ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr); 8712 } 8713 if (!rank) { 8714 count = globalStats.count; 8715 min = globalStats.min; 8716 max = globalStats.max; 8717 mean = globalStats.sum / globalStats.count; 8718 stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8719 } 8720 8721 if (output) { 8722 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); 8723 } 8724 ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 8725 8726 ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 8727 if (dmCoarse) { 8728 PetscBool isplex; 8729 8730 ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 8731 if (isplex) { 8732 ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr); 8733 } 8734 } 8735 PetscFunctionReturn(0); 8736 } 8737 8738 /*@ 8739 DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8740 orthogonal quality below given tolerance. 8741 8742 Collective on dm 8743 8744 Input Parameters: 8745 + dm - The DMPlex object 8746 . fv - Optional PetscFV object for pre-computed cell/face centroid information 8747 - atol - [0, 1] Absolute tolerance for tagging cells. 8748 8749 Output Parameters: 8750 + OrthQual - Vec containing orthogonal quality per cell 8751 - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8752 8753 Options Database Keys: 8754 + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8755 supported. 8756 - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8757 8758 Notes: 8759 Orthogonal quality is given by the following formula: 8760 8761 \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8762 8763 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 8764 is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8765 current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8766 calculating the cosine of the angle between these vectors. 8767 8768 Orthogonal quality ranges from 1 (best) to 0 (worst). 8769 8770 This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8771 pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8772 8773 Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8774 8775 Level: intermediate 8776 8777 .seealso: DMPlexCheckCellShape(), DMCreateLabel() 8778 @*/ 8779 PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8780 { 8781 PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 8782 PetscInt *idx; 8783 PetscScalar *oqVals; 8784 const PetscScalar *cellGeomArr, *faceGeomArr; 8785 PetscReal *ci, *fi, *Ai; 8786 MPI_Comm comm; 8787 Vec cellgeom, facegeom; 8788 DM dmFace, dmCell; 8789 IS glob; 8790 ISLocalToGlobalMapping ltog; 8791 PetscViewer vwr; 8792 PetscErrorCode ierr; 8793 8794 PetscFunctionBegin; 8795 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8796 if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8797 PetscValidPointer(OrthQual, 4); 8798 if (PetscUnlikelyDebug(atol < 0.0 || atol > 1.0)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol); 8799 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8800 ierr = DMGetDimension(dm, &nc);CHKERRQ(ierr); 8801 if (nc < 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc); 8802 { 8803 DMPlexInterpolatedFlag interpFlag; 8804 8805 ierr = DMPlexIsInterpolated(dm, &interpFlag);CHKERRQ(ierr); 8806 if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 8807 PetscMPIInt rank; 8808 8809 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8810 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 8811 } 8812 } 8813 if (OrthQualLabel) { 8814 PetscValidPointer(OrthQualLabel, 5); 8815 ierr = DMCreateLabel(dm, "Orthogonal_Quality");CHKERRQ(ierr); 8816 ierr = DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel);CHKERRQ(ierr); 8817 } else {*OrthQualLabel = NULL;} 8818 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8819 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8820 ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob);CHKERRQ(ierr); 8821 ierr = ISLocalToGlobalMappingCreateIS(glob, <og);CHKERRQ(ierr); 8822 ierr = ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 8823 ierr = VecCreate(comm, OrthQual);CHKERRQ(ierr); 8824 ierr = VecSetType(*OrthQual, VECSTANDARD);CHKERRQ(ierr); 8825 ierr = VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr); 8826 ierr = VecSetLocalToGlobalMapping(*OrthQual, ltog);CHKERRQ(ierr); 8827 ierr = VecSetUp(*OrthQual);CHKERRQ(ierr); 8828 ierr = ISDestroy(&glob);CHKERRQ(ierr); 8829 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 8830 ierr = DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL);CHKERRQ(ierr); 8831 ierr = VecGetArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8832 ierr = VecGetArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8833 ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr); 8834 ierr = VecGetDM(facegeom, &dmFace);CHKERRQ(ierr); 8835 ierr = PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai);CHKERRQ(ierr); 8836 for (cell = cStart; cell < cEnd; cellIter++,cell++) { 8837 PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 8838 PetscInt cellarr[2], *adj = NULL; 8839 PetscScalar *cArr, *fArr; 8840 PetscReal minvalc = 1.0, minvalf = 1.0; 8841 PetscFVCellGeom *cg; 8842 8843 idx[cellIter] = cell-cStart; 8844 cellarr[0] = cell; 8845 /* Make indexing into cellGeom easier */ 8846 ierr = DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg);CHKERRQ(ierr); 8847 ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj);CHKERRQ(ierr); 8848 /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 8849 ierr = PetscCalloc2(adjSize, &cArr, adjSize, &fArr);CHKERRQ(ierr); 8850 for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 8851 PetscInt i; 8852 const PetscInt neigh = adj[cellneigh]; 8853 PetscReal normci = 0, normfi = 0, normai = 0; 8854 PetscFVCellGeom *cgneigh; 8855 PetscFVFaceGeom *fg; 8856 8857 /* Don't count ourselves in the neighbor list */ 8858 if (neigh == cell) continue; 8859 ierr = DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh);CHKERRQ(ierr); 8860 cellarr[1] = neigh; 8861 { 8862 PetscInt numcovpts; 8863 const PetscInt *covpts; 8864 8865 ierr = DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 8866 ierr = DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg);CHKERRQ(ierr); 8867 ierr = DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 8868 } 8869 8870 /* Compute c_i, f_i and their norms */ 8871 for (i = 0; i < nc; i++) { 8872 ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 8873 fi[i] = fg->centroid[i] - cg->centroid[i]; 8874 Ai[i] = fg->normal[i]; 8875 normci += PetscPowReal(ci[i], 2); 8876 normfi += PetscPowReal(fi[i], 2); 8877 normai += PetscPowReal(Ai[i], 2); 8878 } 8879 normci = PetscSqrtReal(normci); 8880 normfi = PetscSqrtReal(normfi); 8881 normai = PetscSqrtReal(normai); 8882 8883 /* Normalize and compute for each face-cell-normal pair */ 8884 for (i = 0; i < nc; i++) { 8885 ci[i] = ci[i]/normci; 8886 fi[i] = fi[i]/normfi; 8887 Ai[i] = Ai[i]/normai; 8888 /* PetscAbs because I don't know if normals are guaranteed to point out */ 8889 cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 8890 fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 8891 } 8892 if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 8893 minvalc = PetscRealPart(cArr[cellneighiter]); 8894 } 8895 if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 8896 minvalf = PetscRealPart(fArr[cellneighiter]); 8897 } 8898 } 8899 ierr = PetscFree(adj);CHKERRQ(ierr); 8900 ierr = PetscFree2(cArr, fArr);CHKERRQ(ierr); 8901 /* Defer to cell if they're equal */ 8902 oqVals[cellIter] = PetscMin(minvalf, minvalc); 8903 if (OrthQualLabel) { 8904 if (PetscRealPart(oqVals[cellIter]) <= atol) {ierr = DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE);CHKERRQ(ierr);} 8905 } 8906 } 8907 ierr = VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES);CHKERRQ(ierr); 8908 ierr = VecAssemblyBegin(*OrthQual);CHKERRQ(ierr); 8909 ierr = VecAssemblyEnd(*OrthQual);CHKERRQ(ierr); 8910 ierr = VecRestoreArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8911 ierr = VecRestoreArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8912 ierr = PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL);CHKERRQ(ierr); 8913 if (OrthQualLabel) { 8914 if (vwr) {ierr = DMLabelView(*OrthQualLabel, vwr);CHKERRQ(ierr);} 8915 } 8916 ierr = PetscFree5(idx, oqVals, ci, fi, Ai);CHKERRQ(ierr); 8917 ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr); 8918 ierr = VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view");CHKERRQ(ierr); 8919 PetscFunctionReturn(0); 8920 } 8921 8922 /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 8923 * interpolator construction */ 8924 static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 8925 { 8926 PetscSection section, newSection, gsection; 8927 PetscSF sf; 8928 PetscBool hasConstraints, ghasConstraints; 8929 PetscErrorCode ierr; 8930 8931 PetscFunctionBegin; 8932 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8933 PetscValidPointer(odm,2); 8934 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 8935 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 8936 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 8937 if (!ghasConstraints) { 8938 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 8939 *odm = dm; 8940 PetscFunctionReturn(0); 8941 } 8942 ierr = DMClone(dm, odm);CHKERRQ(ierr); 8943 ierr = DMCopyFields(dm, *odm);CHKERRQ(ierr); 8944 ierr = DMGetLocalSection(*odm, &newSection);CHKERRQ(ierr); 8945 ierr = DMGetPointSF(*odm, &sf);CHKERRQ(ierr); 8946 ierr = PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 8947 ierr = DMSetGlobalSection(*odm, gsection);CHKERRQ(ierr); 8948 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 8949 PetscFunctionReturn(0); 8950 } 8951 8952 static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 8953 { 8954 DM dmco, dmfo; 8955 Mat interpo; 8956 Vec rscale; 8957 Vec cglobalo, clocal; 8958 Vec fglobal, fglobalo, flocal; 8959 PetscBool regular; 8960 PetscErrorCode ierr; 8961 8962 PetscFunctionBegin; 8963 ierr = DMGetFullDM(dmc, &dmco);CHKERRQ(ierr); 8964 ierr = DMGetFullDM(dmf, &dmfo);CHKERRQ(ierr); 8965 ierr = DMSetCoarseDM(dmfo, dmco);CHKERRQ(ierr); 8966 ierr = DMPlexGetRegularRefinement(dmf, ®ular);CHKERRQ(ierr); 8967 ierr = DMPlexSetRegularRefinement(dmfo, regular);CHKERRQ(ierr); 8968 ierr = DMCreateInterpolation(dmco, dmfo, &interpo, &rscale);CHKERRQ(ierr); 8969 ierr = DMCreateGlobalVector(dmco, &cglobalo);CHKERRQ(ierr); 8970 ierr = DMCreateLocalVector(dmc, &clocal);CHKERRQ(ierr); 8971 ierr = VecSet(cglobalo, 0.);CHKERRQ(ierr); 8972 ierr = VecSet(clocal, 0.);CHKERRQ(ierr); 8973 ierr = DMCreateGlobalVector(dmf, &fglobal);CHKERRQ(ierr); 8974 ierr = DMCreateGlobalVector(dmfo, &fglobalo);CHKERRQ(ierr); 8975 ierr = DMCreateLocalVector(dmf, &flocal);CHKERRQ(ierr); 8976 ierr = VecSet(fglobal, 0.);CHKERRQ(ierr); 8977 ierr = VecSet(fglobalo, 0.);CHKERRQ(ierr); 8978 ierr = VecSet(flocal, 0.);CHKERRQ(ierr); 8979 ierr = DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL);CHKERRQ(ierr); 8980 ierr = DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 8981 ierr = DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 8982 ierr = MatMult(interpo, cglobalo, fglobalo);CHKERRQ(ierr); 8983 ierr = DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 8984 ierr = DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 8985 ierr = DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 8986 ierr = DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 8987 *shift = fglobal; 8988 ierr = VecDestroy(&flocal);CHKERRQ(ierr); 8989 ierr = VecDestroy(&fglobalo);CHKERRQ(ierr); 8990 ierr = VecDestroy(&clocal);CHKERRQ(ierr); 8991 ierr = VecDestroy(&cglobalo);CHKERRQ(ierr); 8992 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 8993 ierr = MatDestroy(&interpo);CHKERRQ(ierr); 8994 ierr = DMDestroy(&dmfo);CHKERRQ(ierr); 8995 ierr = DMDestroy(&dmco);CHKERRQ(ierr); 8996 PetscFunctionReturn(0); 8997 } 8998 8999 PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9000 { 9001 PetscObject shifto; 9002 Vec shift; 9003 9004 PetscErrorCode ierr; 9005 9006 PetscFunctionBegin; 9007 if (!interp) { 9008 Vec rscale; 9009 9010 ierr = DMCreateInterpolation(coarse, fine, &interp, &rscale);CHKERRQ(ierr); 9011 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9012 } else { 9013 ierr = PetscObjectReference((PetscObject)interp);CHKERRQ(ierr); 9014 } 9015 ierr = PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto);CHKERRQ(ierr); 9016 if (!shifto) { 9017 ierr = DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift);CHKERRQ(ierr); 9018 ierr = PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift);CHKERRQ(ierr); 9019 shifto = (PetscObject) shift; 9020 ierr = VecDestroy(&shift);CHKERRQ(ierr); 9021 } 9022 shift = (Vec) shifto; 9023 ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr); 9024 ierr = VecAXPY(fineSol, 1.0, shift);CHKERRQ(ierr); 9025 ierr = MatDestroy(&interp);CHKERRQ(ierr); 9026 PetscFunctionReturn(0); 9027 } 9028 9029 /* Pointwise interpolation 9030 Just code FEM for now 9031 u^f = I u^c 9032 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 9033 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 9034 I_{ij} = psi^f_i phi^c_j 9035 */ 9036 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9037 { 9038 PetscSection gsc, gsf; 9039 PetscInt m, n; 9040 void *ctx; 9041 DM cdm; 9042 PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9043 PetscErrorCode ierr; 9044 9045 PetscFunctionBegin; 9046 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9047 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9048 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9049 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9050 9051 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 9052 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 9053 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9054 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 9055 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9056 9057 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9058 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9059 if (!isRefined || (regular && cdm == dmCoarse)) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx);CHKERRQ(ierr);} 9060 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 9061 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 9062 if (scaling) { 9063 /* Use naive scaling */ 9064 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 9065 } 9066 PetscFunctionReturn(0); 9067 } 9068 9069 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9070 { 9071 PetscErrorCode ierr; 9072 VecScatter ctx; 9073 9074 PetscFunctionBegin; 9075 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 9076 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 9077 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 9078 PetscFunctionReturn(0); 9079 } 9080 9081 static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9082 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9083 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9084 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 9085 { 9086 g0[0] = 1.0; 9087 } 9088 9089 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9090 { 9091 PetscSection gsc, gsf; 9092 PetscInt m, n; 9093 void *ctx; 9094 DM cdm; 9095 PetscBool regular; 9096 PetscErrorCode ierr; 9097 9098 PetscFunctionBegin; 9099 if (dmFine == dmCoarse) { 9100 DM dmc; 9101 PetscDS ds; 9102 Vec u; 9103 IS cellIS; 9104 PetscFormKey key; 9105 PetscInt depth; 9106 9107 ierr = DMClone(dmFine, &dmc);CHKERRQ(ierr); 9108 ierr = DMCopyDisc(dmFine, dmc);CHKERRQ(ierr); 9109 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9110 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9111 ierr = DMCreateMatrix(dmc, mass);CHKERRQ(ierr); 9112 ierr = DMGetGlobalVector(dmc, &u);CHKERRQ(ierr); 9113 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9114 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9115 ierr = MatZeroEntries(*mass);CHKERRQ(ierr); 9116 key.label = NULL; 9117 key.value = 0; 9118 key.field = 0; 9119 key.part = 0; 9120 ierr = DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL);CHKERRQ(ierr); 9121 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9122 ierr = DMRestoreGlobalVector(dmc, &u);CHKERRQ(ierr); 9123 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9124 } else { 9125 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9126 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9127 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9128 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9129 9130 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 9131 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9132 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 9133 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9134 9135 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9136 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9137 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9138 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9139 } 9140 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 9141 PetscFunctionReturn(0); 9142 } 9143 9144 /*@ 9145 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9146 9147 Input Parameter: 9148 . dm - The DMPlex object 9149 9150 Output Parameter: 9151 . regular - The flag 9152 9153 Level: intermediate 9154 9155 .seealso: DMPlexSetRegularRefinement() 9156 @*/ 9157 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 9158 { 9159 PetscFunctionBegin; 9160 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9161 PetscValidPointer(regular, 2); 9162 *regular = ((DM_Plex *) dm->data)->regularRefinement; 9163 PetscFunctionReturn(0); 9164 } 9165 9166 /*@ 9167 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9168 9169 Input Parameters: 9170 + dm - The DMPlex object 9171 - regular - The flag 9172 9173 Level: intermediate 9174 9175 .seealso: DMPlexGetRegularRefinement() 9176 @*/ 9177 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 9178 { 9179 PetscFunctionBegin; 9180 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9181 ((DM_Plex *) dm->data)->regularRefinement = regular; 9182 PetscFunctionReturn(0); 9183 } 9184 9185 /*@ 9186 DMPlexGetCellRefinerType - Get the strategy for refining a cell 9187 9188 Input Parameter: 9189 . dm - The DMPlex object 9190 9191 Output Parameter: 9192 . cr - The strategy number 9193 9194 Level: intermediate 9195 9196 .seealso: DMPlexSetCellRefinerType(), DMPlexSetRegularRefinement() 9197 @*/ 9198 PetscErrorCode DMPlexGetCellRefinerType(DM dm, DMPlexCellRefinerType *cr) 9199 { 9200 PetscFunctionBegin; 9201 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9202 PetscValidPointer(cr, 2); 9203 *cr = ((DM_Plex *) dm->data)->cellRefiner; 9204 PetscFunctionReturn(0); 9205 } 9206 9207 /*@ 9208 DMPlexSetCellRefinerType - Set the strategy for refining a cell 9209 9210 Input Parameters: 9211 + dm - The DMPlex object 9212 - cr - The strategy number 9213 9214 Level: intermediate 9215 9216 .seealso: DMPlexGetCellRefinerType(), DMPlexGetRegularRefinement() 9217 @*/ 9218 PetscErrorCode DMPlexSetCellRefinerType(DM dm, DMPlexCellRefinerType cr) 9219 { 9220 PetscFunctionBegin; 9221 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9222 ((DM_Plex *) dm->data)->cellRefiner = cr; 9223 PetscFunctionReturn(0); 9224 } 9225 9226 /* anchors */ 9227 /*@ 9228 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9229 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 9230 9231 not collective 9232 9233 Input Parameters: 9234 . dm - The DMPlex object 9235 9236 Output Parameters: 9237 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9238 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9239 9240 Level: intermediate 9241 9242 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 9243 @*/ 9244 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9245 { 9246 DM_Plex *plex = (DM_Plex *)dm->data; 9247 PetscErrorCode ierr; 9248 9249 PetscFunctionBegin; 9250 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9251 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 9252 if (anchorSection) *anchorSection = plex->anchorSection; 9253 if (anchorIS) *anchorIS = plex->anchorIS; 9254 PetscFunctionReturn(0); 9255 } 9256 9257 /*@ 9258 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9259 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9260 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9261 9262 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9263 DMGetConstraints() and filling in the entries in the constraint matrix. 9264 9265 collective on dm 9266 9267 Input Parameters: 9268 + dm - The DMPlex object 9269 . 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). 9270 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9271 9272 The reference counts of anchorSection and anchorIS are incremented. 9273 9274 Level: intermediate 9275 9276 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 9277 @*/ 9278 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9279 { 9280 DM_Plex *plex = (DM_Plex *)dm->data; 9281 PetscMPIInt result; 9282 PetscErrorCode ierr; 9283 9284 PetscFunctionBegin; 9285 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9286 if (anchorSection) { 9287 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 9288 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRMPI(ierr); 9289 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9290 } 9291 if (anchorIS) { 9292 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 9293 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRMPI(ierr); 9294 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9295 } 9296 9297 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 9298 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 9299 plex->anchorSection = anchorSection; 9300 9301 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 9302 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 9303 plex->anchorIS = anchorIS; 9304 9305 if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9306 PetscInt size, a, pStart, pEnd; 9307 const PetscInt *anchors; 9308 9309 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9310 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 9311 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 9312 for (a = 0; a < size; a++) { 9313 PetscInt p; 9314 9315 p = anchors[a]; 9316 if (p >= pStart && p < pEnd) { 9317 PetscInt dof; 9318 9319 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9320 if (dof) { 9321 PetscErrorCode ierr2; 9322 9323 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 9324 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 9325 } 9326 } 9327 } 9328 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 9329 } 9330 /* reset the generic constraints */ 9331 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 9332 PetscFunctionReturn(0); 9333 } 9334 9335 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9336 { 9337 PetscSection anchorSection; 9338 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9339 PetscErrorCode ierr; 9340 9341 PetscFunctionBegin; 9342 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9343 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9344 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 9345 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9346 if (numFields) { 9347 PetscInt f; 9348 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 9349 9350 for (f = 0; f < numFields; f++) { 9351 PetscInt numComp; 9352 9353 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 9354 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 9355 } 9356 } 9357 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9358 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9359 pStart = PetscMax(pStart,sStart); 9360 pEnd = PetscMin(pEnd,sEnd); 9361 pEnd = PetscMax(pStart,pEnd); 9362 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 9363 for (p = pStart; p < pEnd; p++) { 9364 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9365 if (dof) { 9366 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 9367 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 9368 for (f = 0; f < numFields; f++) { 9369 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 9370 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 9371 } 9372 } 9373 } 9374 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 9375 ierr = PetscObjectSetName((PetscObject) *cSec, "Constraint Section");CHKERRQ(ierr); 9376 PetscFunctionReturn(0); 9377 } 9378 9379 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9380 { 9381 PetscSection aSec; 9382 PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 9383 const PetscInt *anchors; 9384 PetscInt numFields, f; 9385 IS aIS; 9386 PetscErrorCode ierr; 9387 MatType mtype; 9388 PetscBool iscuda,iskokkos; 9389 9390 PetscFunctionBegin; 9391 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9392 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 9393 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 9394 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 9395 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 9396 ierr = PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr); 9397 if (!iscuda) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr); } 9398 ierr = PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos);CHKERRQ(ierr); 9399 if (!iskokkos) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos);CHKERRQ(ierr); } 9400 if (iscuda) mtype = MATSEQAIJCUSPARSE; 9401 else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9402 else mtype = MATSEQAIJ; 9403 ierr = MatSetType(*cMat,mtype);CHKERRQ(ierr); 9404 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 9405 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 9406 /* cSec will be a subset of aSec and section */ 9407 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 9408 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9409 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 9410 i[0] = 0; 9411 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9412 for (p = pStart; p < pEnd; p++) { 9413 PetscInt rDof, rOff, r; 9414 9415 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9416 if (!rDof) continue; 9417 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9418 if (numFields) { 9419 for (f = 0; f < numFields; f++) { 9420 annz = 0; 9421 for (r = 0; r < rDof; r++) { 9422 a = anchors[rOff + r]; 9423 if (a < sStart || a >= sEnd) continue; 9424 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9425 annz += aDof; 9426 } 9427 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9428 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 9429 for (q = 0; q < dof; q++) { 9430 i[off + q + 1] = i[off + q] + annz; 9431 } 9432 } 9433 } 9434 else { 9435 annz = 0; 9436 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9437 for (q = 0; q < dof; q++) { 9438 a = anchors[rOff + q]; 9439 if (a < sStart || a >= sEnd) continue; 9440 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9441 annz += aDof; 9442 } 9443 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9444 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 9445 for (q = 0; q < dof; q++) { 9446 i[off + q + 1] = i[off + q] + annz; 9447 } 9448 } 9449 } 9450 nnz = i[m]; 9451 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 9452 offset = 0; 9453 for (p = pStart; p < pEnd; p++) { 9454 if (numFields) { 9455 for (f = 0; f < numFields; f++) { 9456 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9457 for (q = 0; q < dof; q++) { 9458 PetscInt rDof, rOff, r; 9459 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9460 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9461 for (r = 0; r < rDof; r++) { 9462 PetscInt s; 9463 9464 a = anchors[rOff + r]; 9465 if (a < sStart || a >= sEnd) continue; 9466 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9467 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 9468 for (s = 0; s < aDof; s++) { 9469 j[offset++] = aOff + s; 9470 } 9471 } 9472 } 9473 } 9474 } 9475 else { 9476 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9477 for (q = 0; q < dof; q++) { 9478 PetscInt rDof, rOff, r; 9479 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9480 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9481 for (r = 0; r < rDof; r++) { 9482 PetscInt s; 9483 9484 a = anchors[rOff + r]; 9485 if (a < sStart || a >= sEnd) continue; 9486 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9487 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 9488 for (s = 0; s < aDof; s++) { 9489 j[offset++] = aOff + s; 9490 } 9491 } 9492 } 9493 } 9494 } 9495 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 9496 ierr = PetscFree(i);CHKERRQ(ierr); 9497 ierr = PetscFree(j);CHKERRQ(ierr); 9498 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 9499 PetscFunctionReturn(0); 9500 } 9501 9502 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 9503 { 9504 DM_Plex *plex = (DM_Plex *)dm->data; 9505 PetscSection anchorSection, section, cSec; 9506 Mat cMat; 9507 PetscErrorCode ierr; 9508 9509 PetscFunctionBegin; 9510 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9511 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9512 if (anchorSection) { 9513 PetscInt Nf; 9514 9515 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 9516 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 9517 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 9518 ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 9519 if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 9520 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 9521 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 9522 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 9523 } 9524 PetscFunctionReturn(0); 9525 } 9526 9527 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9528 { 9529 IS subis; 9530 PetscSection section, subsection; 9531 PetscErrorCode ierr; 9532 9533 PetscFunctionBegin; 9534 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9535 if (!section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 9536 if (!subdm) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9537 /* Create subdomain */ 9538 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 9539 /* Create submodel */ 9540 ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr); 9541 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 9542 ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr); 9543 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 9544 ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 9545 /* Create map from submodel to global model */ 9546 if (is) { 9547 PetscSection sectionGlobal, subsectionGlobal; 9548 IS spIS; 9549 const PetscInt *spmap; 9550 PetscInt *subIndices; 9551 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9552 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9553 9554 ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 9555 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 9556 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 9557 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 9558 ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 9559 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 9560 for (p = pStart; p < pEnd; ++p) { 9561 PetscInt gdof, pSubSize = 0; 9562 9563 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 9564 if (gdof > 0) { 9565 for (f = 0; f < Nf; ++f) { 9566 PetscInt fdof, fcdof; 9567 9568 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 9569 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 9570 pSubSize += fdof-fcdof; 9571 } 9572 subSize += pSubSize; 9573 if (pSubSize) { 9574 if (bs < 0) { 9575 bs = pSubSize; 9576 } else if (bs != pSubSize) { 9577 /* Layout does not admit a pointwise block size */ 9578 bs = 1; 9579 } 9580 } 9581 } 9582 } 9583 /* Must have same blocksize on all procs (some might have no points) */ 9584 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 9585 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 9586 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9587 else {bs = bsMinMax[0];} 9588 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 9589 for (p = pStart; p < pEnd; ++p) { 9590 PetscInt gdof, goff; 9591 9592 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 9593 if (gdof > 0) { 9594 const PetscInt point = spmap[p]; 9595 9596 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 9597 for (f = 0; f < Nf; ++f) { 9598 PetscInt fdof, fcdof, fc, f2, poff = 0; 9599 9600 /* Can get rid of this loop by storing field information in the global section */ 9601 for (f2 = 0; f2 < f; ++f2) { 9602 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 9603 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 9604 poff += fdof-fcdof; 9605 } 9606 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 9607 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 9608 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9609 subIndices[subOff] = goff+poff+fc; 9610 } 9611 } 9612 } 9613 } 9614 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 9615 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 9616 if (bs > 1) { 9617 /* We need to check that the block size does not come from non-contiguous fields */ 9618 PetscInt i, j, set = 1; 9619 for (i = 0; i < subSize; i += bs) { 9620 for (j = 0; j < bs; ++j) { 9621 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9622 } 9623 } 9624 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 9625 } 9626 /* Attach nullspace */ 9627 for (f = 0; f < Nf; ++f) { 9628 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9629 if ((*subdm)->nullspaceConstructors[f]) break; 9630 } 9631 if (f < Nf) { 9632 MatNullSpace nullSpace; 9633 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace);CHKERRQ(ierr); 9634 9635 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 9636 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 9637 } 9638 } 9639 PetscFunctionReturn(0); 9640 } 9641 9642 /*@ 9643 DMPlexMonitorThroughput - Report the cell throughput of FE integration 9644 9645 Input Parameter: 9646 - dm - The DM 9647 9648 Level: developer 9649 9650 Options Database Keys: 9651 . -dm_plex_monitor_throughput - Activate the monitor 9652 9653 .seealso: DMSetFromOptions(), DMPlexCreate() 9654 @*/ 9655 PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9656 { 9657 #if defined(PETSC_USE_LOG) 9658 PetscStageLog stageLog; 9659 PetscLogEvent event; 9660 PetscLogStage stage; 9661 PetscEventPerfInfo eventInfo; 9662 PetscReal cellRate, flopRate; 9663 PetscInt cStart, cEnd, Nf, N; 9664 const char *name; 9665 PetscErrorCode ierr; 9666 #endif 9667 9668 PetscFunctionBegin; 9669 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9670 #if defined(PETSC_USE_LOG) 9671 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 9672 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9673 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9674 ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 9675 ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr); 9676 ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr); 9677 ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr); 9678 N = (cEnd - cStart)*Nf*eventInfo.count; 9679 flopRate = eventInfo.flops/eventInfo.time; 9680 cellRate = N/eventInfo.time; 9681 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); 9682 #else 9683 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9684 #endif 9685 PetscFunctionReturn(0); 9686 } 9687