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