1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petsc/private/isimpl.h> 3 #include <petsc/private/vecimpl.h> 4 #include <petsc/private/glvisvecimpl.h> 5 #include <petscsf.h> 6 #include <petscds.h> 7 #include <petscdraw.h> 8 #include <petscdmfield.h> 9 #include <petscdmplextransform.h> 10 11 /* Logging support */ 12 PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF,DMPLEX_LocatePoints; 13 14 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 15 16 /*@ 17 DMPlexIsSimplex - Is the first cell in this mesh a simplex? 18 19 Input Parameter: 20 . dm - The DMPlex object 21 22 Output Parameter: 23 . simplex - Flag checking for a simplex 24 25 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 26 If the mesh has no cells, this returns PETSC_FALSE. 27 28 Level: intermediate 29 30 .seealso DMPlexGetSimplexOrBoxCells(), DMPlexGetCellType(), DMPlexGetHeightStratum(), DMPolytopeTypeGetNumVertices() 31 @*/ 32 PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 33 { 34 DMPolytopeType ct; 35 PetscInt cStart, cEnd; 36 PetscErrorCode ierr; 37 38 PetscFunctionBegin; 39 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 40 if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);} 41 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 42 *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 43 PetscFunctionReturn(0); 44 } 45 46 /*@ 47 DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 48 49 Input Parameters: 50 + dm - The DMPlex object 51 - height - The cell height in the Plex, 0 is the default 52 53 Output Parameters: 54 + cStart - The first "normal" cell 55 - cEnd - The upper bound on "normal"" cells 56 57 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 58 59 Level: developer 60 61 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 62 @*/ 63 PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 64 { 65 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 66 PetscInt cS, cE, c; 67 PetscErrorCode ierr; 68 69 PetscFunctionBegin; 70 ierr = DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE);CHKERRQ(ierr); 71 for (c = cS; c < cE; ++c) { 72 DMPolytopeType cct; 73 74 ierr = DMPlexGetCellType(dm, c, &cct);CHKERRQ(ierr); 75 if ((PetscInt) cct < 0) break; 76 switch (cct) { 77 case DM_POLYTOPE_POINT: 78 case DM_POLYTOPE_SEGMENT: 79 case DM_POLYTOPE_TRIANGLE: 80 case DM_POLYTOPE_QUADRILATERAL: 81 case DM_POLYTOPE_TETRAHEDRON: 82 case DM_POLYTOPE_HEXAHEDRON: 83 ct = cct; 84 break; 85 default: break; 86 } 87 if (ct != DM_POLYTOPE_UNKNOWN) break; 88 } 89 if (ct != DM_POLYTOPE_UNKNOWN) { 90 DMLabel ctLabel; 91 92 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 93 ierr = DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE);CHKERRQ(ierr); 94 } 95 if (cStart) *cStart = cS; 96 if (cEnd) *cEnd = cE; 97 PetscFunctionReturn(0); 98 } 99 100 PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 101 { 102 PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 103 PetscInt vcdof[2] = {0,0}, globalvcdof[2]; 104 PetscErrorCode ierr; 105 106 PetscFunctionBegin; 107 *ft = PETSC_VTK_INVALID; 108 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 109 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 110 ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 111 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 112 if (field >= 0) { 113 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]);CHKERRQ(ierr);} 114 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]);CHKERRQ(ierr);} 115 } else { 116 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vcdof[0]);CHKERRQ(ierr);} 117 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &vcdof[1]);CHKERRQ(ierr);} 118 } 119 ierr = MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 120 if (globalvcdof[0]) { 121 *sStart = vStart; 122 *sEnd = vEnd; 123 if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 124 else *ft = PETSC_VTK_POINT_FIELD; 125 } else if (globalvcdof[1]) { 126 *sStart = cStart; 127 *sEnd = cEnd; 128 if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 129 else *ft = PETSC_VTK_CELL_FIELD; 130 } else { 131 if (field >= 0) { 132 const char *fieldname; 133 134 ierr = PetscSectionGetFieldName(section, field, &fieldname);CHKERRQ(ierr); 135 ierr = PetscInfo2((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname);CHKERRQ(ierr); 136 } else { 137 ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\"%s\"\n");CHKERRQ(ierr); 138 } 139 } 140 PetscFunctionReturn(0); 141 } 142 143 static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 144 { 145 DM dm; 146 PetscSection s; 147 PetscDraw draw, popup; 148 DM cdm; 149 PetscSection coordSection; 150 Vec coordinates; 151 const PetscScalar *coords, *array; 152 PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 153 PetscReal vbound[2], time; 154 PetscBool isnull, flg; 155 PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 156 const char *name; 157 char title[PETSC_MAX_PATH_LEN]; 158 PetscErrorCode ierr; 159 160 PetscFunctionBegin; 161 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 162 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 163 if (isnull) PetscFunctionReturn(0); 164 165 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 166 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 167 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D. Use PETSCVIEWERGLVIS", dim); 168 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 169 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 170 ierr = DMGetCoarsenLevel(dm, &level);CHKERRQ(ierr); 171 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 172 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 173 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 174 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 175 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 176 177 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 178 ierr = DMGetOutputSequenceNumber(dm, &step, &time);CHKERRQ(ierr); 179 180 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 181 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 182 for (c = 0; c < N; c += dim) { 183 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 184 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 185 } 186 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 187 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 188 189 /* Could implement something like DMDASelectFields() */ 190 for (f = 0; f < Nf; ++f) { 191 DM fdm = dm; 192 Vec fv = v; 193 IS fis; 194 char prefix[PETSC_MAX_PATH_LEN]; 195 const char *fname; 196 197 ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr); 198 ierr = PetscSectionGetFieldName(s, f, &fname);CHKERRQ(ierr); 199 200 if (v->hdr.prefix) {ierr = PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix));CHKERRQ(ierr);} 201 else {prefix[0] = '\0';} 202 if (Nf > 1) { 203 ierr = DMCreateSubDM(dm, 1, &f, &fis, &fdm);CHKERRQ(ierr); 204 ierr = VecGetSubVector(v, fis, &fv);CHKERRQ(ierr); 205 ierr = PetscStrlcat(prefix, fname,sizeof(prefix));CHKERRQ(ierr); 206 ierr = PetscStrlcat(prefix, "_",sizeof(prefix));CHKERRQ(ierr); 207 } 208 for (comp = 0; comp < Nc; ++comp, ++w) { 209 PetscInt nmax = 2; 210 211 ierr = PetscViewerDrawGetDraw(viewer, w, &draw);CHKERRQ(ierr); 212 if (Nc > 1) {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time);CHKERRQ(ierr);} 213 else {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time);CHKERRQ(ierr);} 214 ierr = PetscDrawSetTitle(draw, title);CHKERRQ(ierr); 215 216 /* TODO Get max and min only for this component */ 217 ierr = PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg);CHKERRQ(ierr); 218 if (!flg) { 219 ierr = VecMin(fv, NULL, &vbound[0]);CHKERRQ(ierr); 220 ierr = VecMax(fv, NULL, &vbound[1]);CHKERRQ(ierr); 221 if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 222 } 223 ierr = PetscDrawGetPopup(draw, &popup);CHKERRQ(ierr); 224 ierr = PetscDrawScalePopup(popup, vbound[0], vbound[1]);CHKERRQ(ierr); 225 ierr = PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]);CHKERRQ(ierr); 226 227 ierr = VecGetArrayRead(fv, &array);CHKERRQ(ierr); 228 for (c = cStart; c < cEnd; ++c) { 229 PetscScalar *coords = NULL, *a = NULL; 230 PetscInt numCoords, color[4] = {-1,-1,-1,-1}; 231 232 ierr = DMPlexPointLocalRead(fdm, c, array, &a);CHKERRQ(ierr); 233 if (a) { 234 color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 235 color[1] = color[2] = color[3] = color[0]; 236 } else { 237 PetscScalar *vals = NULL; 238 PetscInt numVals, va; 239 240 ierr = DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 241 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); 242 switch (numVals/Nc) { 243 case 3: /* P1 Triangle */ 244 case 4: /* P1 Quadrangle */ 245 for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]); 246 break; 247 case 6: /* P2 Triangle */ 248 case 8: /* P2 Quadrangle */ 249 for (va = 0; va < numVals/(Nc*2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp + numVals/(Nc*2)]), vbound[0], vbound[1]); 250 break; 251 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc); 252 } 253 ierr = DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 254 } 255 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 256 switch (numCoords) { 257 case 6: 258 case 12: /* Localized triangle */ 259 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 260 break; 261 case 8: 262 case 16: /* Localized quadrilateral */ 263 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 264 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0]);CHKERRQ(ierr); 265 break; 266 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords); 267 } 268 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 269 } 270 ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr); 271 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 272 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 273 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 274 } 275 if (Nf > 1) { 276 ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr); 277 ierr = ISDestroy(&fis);CHKERRQ(ierr); 278 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 279 } 280 } 281 PetscFunctionReturn(0); 282 } 283 284 static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 285 { 286 DM dm; 287 Vec locv; 288 const char *name; 289 PetscSection section; 290 PetscInt pStart, pEnd; 291 PetscInt numFields; 292 PetscViewerVTKFieldType ft; 293 PetscErrorCode ierr; 294 295 PetscFunctionBegin; 296 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 297 ierr = DMCreateLocalVector(dm, &locv);CHKERRQ(ierr); /* VTK viewer requires exclusive ownership of the vector */ 298 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 299 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 300 ierr = VecCopy(v, locv);CHKERRQ(ierr); 301 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 302 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 303 if (!numFields) { 304 ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 305 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 306 } else { 307 PetscInt f; 308 309 for (f = 0; f < numFields; f++) { 310 ierr = DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft);CHKERRQ(ierr); 311 if (ft == PETSC_VTK_INVALID) continue; 312 ierr = PetscObjectReference((PetscObject)locv);CHKERRQ(ierr); 313 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 314 } 315 ierr = VecDestroy(&locv);CHKERRQ(ierr); 316 } 317 PetscFunctionReturn(0); 318 } 319 320 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 321 { 322 DM dm; 323 PetscBool isvtk, ishdf5, isdraw, isglvis; 324 PetscErrorCode ierr; 325 326 PetscFunctionBegin; 327 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 328 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 329 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 330 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 331 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 332 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 333 if (isvtk || ishdf5 || isdraw || isglvis) { 334 PetscInt i,numFields; 335 PetscObject fe; 336 PetscBool fem = PETSC_FALSE; 337 Vec locv = v; 338 const char *name; 339 PetscInt step; 340 PetscReal time; 341 342 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 343 for (i=0; i<numFields; i++) { 344 ierr = DMGetField(dm, i, NULL, &fe);CHKERRQ(ierr); 345 if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; } 346 } 347 if (fem) { 348 PetscObject isZero; 349 350 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 351 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 352 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 353 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 354 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 355 ierr = VecCopy(v, locv);CHKERRQ(ierr); 356 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 357 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr); 358 } 359 if (isvtk) { 360 ierr = VecView_Plex_Local_VTK(locv, viewer);CHKERRQ(ierr); 361 } else if (ishdf5) { 362 #if defined(PETSC_HAVE_HDF5) 363 ierr = VecView_Plex_Local_HDF5_Internal(locv, viewer);CHKERRQ(ierr); 364 #else 365 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 366 #endif 367 } else if (isdraw) { 368 ierr = VecView_Plex_Local_Draw(locv, viewer);CHKERRQ(ierr); 369 } else if (isglvis) { 370 ierr = DMGetOutputSequenceNumber(dm, &step, NULL);CHKERRQ(ierr); 371 ierr = PetscViewerGLVisSetSnapId(viewer, step);CHKERRQ(ierr); 372 ierr = VecView_GLVis(locv, viewer);CHKERRQ(ierr); 373 } 374 if (fem) { 375 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 376 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 377 } 378 } else { 379 PetscBool isseq; 380 381 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 382 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 383 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 384 } 385 PetscFunctionReturn(0); 386 } 387 388 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 389 { 390 DM dm; 391 PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii; 392 PetscErrorCode ierr; 393 394 PetscFunctionBegin; 395 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 396 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 397 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 398 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 399 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 400 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 401 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 402 if (isvtk || isdraw || isglvis) { 403 Vec locv; 404 PetscObject isZero; 405 const char *name; 406 407 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 408 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 409 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 410 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 411 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 412 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 413 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 414 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 415 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 416 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 417 } else if (ishdf5) { 418 #if defined(PETSC_HAVE_HDF5) 419 ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 420 #else 421 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 422 #endif 423 } else if (isexodusii) { 424 #if defined(PETSC_HAVE_EXODUSII) 425 ierr = VecView_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 426 #else 427 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 428 #endif 429 } else { 430 PetscBool isseq; 431 432 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 433 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 434 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 435 } 436 PetscFunctionReturn(0); 437 } 438 439 PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 440 { 441 DM dm; 442 MPI_Comm comm; 443 PetscViewerFormat format; 444 Vec v; 445 PetscBool isvtk, ishdf5; 446 PetscErrorCode ierr; 447 448 PetscFunctionBegin; 449 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 450 ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 451 if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 452 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 453 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 454 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 455 if (format == PETSC_VIEWER_NATIVE) { 456 /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 457 /* this need a better fix */ 458 if (dm->useNatural) { 459 if (dm->sfNatural) { 460 const char *vecname; 461 PetscInt n, nroots; 462 463 ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr); 464 ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 465 if (n == nroots) { 466 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 467 ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 468 ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 469 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 470 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 471 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 472 } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 473 } else v = originalv; 474 } else v = originalv; 475 476 if (ishdf5) { 477 #if defined(PETSC_HAVE_HDF5) 478 ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 479 #else 480 SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 481 #endif 482 } else if (isvtk) { 483 SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 484 } else { 485 PetscBool isseq; 486 487 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 488 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 489 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 490 } 491 if (v != originalv) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 492 PetscFunctionReturn(0); 493 } 494 495 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 496 { 497 DM dm; 498 PetscBool ishdf5; 499 PetscErrorCode ierr; 500 501 PetscFunctionBegin; 502 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 503 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 504 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 505 if (ishdf5) { 506 DM dmBC; 507 Vec gv; 508 const char *name; 509 510 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 511 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 512 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 513 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 514 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 515 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 516 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 517 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 518 } else { 519 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 520 } 521 PetscFunctionReturn(0); 522 } 523 524 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 525 { 526 DM dm; 527 PetscBool ishdf5,isexodusii; 528 PetscErrorCode ierr; 529 530 PetscFunctionBegin; 531 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 532 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 533 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 534 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 535 if (ishdf5) { 536 #if defined(PETSC_HAVE_HDF5) 537 ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 538 #else 539 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 540 #endif 541 } else if (isexodusii) { 542 #if defined(PETSC_HAVE_EXODUSII) 543 ierr = VecLoad_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 544 #else 545 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 546 #endif 547 } else { 548 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 549 } 550 PetscFunctionReturn(0); 551 } 552 553 PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 554 { 555 DM dm; 556 PetscViewerFormat format; 557 PetscBool ishdf5; 558 PetscErrorCode ierr; 559 560 PetscFunctionBegin; 561 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 562 if (!dm) SETERRQ(PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 563 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 564 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 565 if (format == PETSC_VIEWER_NATIVE) { 566 if (dm->useNatural) { 567 if (dm->sfNatural) { 568 if (ishdf5) { 569 #if defined(PETSC_HAVE_HDF5) 570 Vec v; 571 const char *vecname; 572 573 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 574 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 575 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 576 ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 577 ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 578 ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 579 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 580 #else 581 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 582 #endif 583 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 584 } 585 } else { 586 ierr = VecLoad_Default(originalv, viewer);CHKERRQ(ierr); 587 } 588 } 589 PetscFunctionReturn(0); 590 } 591 592 PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 593 { 594 PetscSection coordSection; 595 Vec coordinates; 596 DMLabel depthLabel, celltypeLabel; 597 const char *name[4]; 598 const PetscScalar *a; 599 PetscInt dim, pStart, pEnd, cStart, cEnd, c; 600 PetscErrorCode ierr; 601 602 PetscFunctionBegin; 603 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 604 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 605 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 606 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 607 ierr = DMPlexGetCellTypeLabel(dm, &celltypeLabel);CHKERRQ(ierr); 608 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 609 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 610 ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 611 name[0] = "vertex"; 612 name[1] = "edge"; 613 name[dim-1] = "face"; 614 name[dim] = "cell"; 615 for (c = cStart; c < cEnd; ++c) { 616 PetscInt *closure = NULL; 617 PetscInt closureSize, cl, ct; 618 619 ierr = DMLabelGetValue(celltypeLabel, c, &ct);CHKERRQ(ierr); 620 ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]);CHKERRQ(ierr); 621 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 622 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 623 for (cl = 0; cl < closureSize*2; cl += 2) { 624 PetscInt point = closure[cl], depth, dof, off, d, p; 625 626 if ((point < pStart) || (point >= pEnd)) continue; 627 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 628 if (!dof) continue; 629 ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 630 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 631 ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr); 632 for (p = 0; p < dof/dim; ++p) { 633 ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 634 for (d = 0; d < dim; ++d) { 635 if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 636 ierr = PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 637 } 638 ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 639 } 640 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 641 } 642 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 643 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 644 } 645 ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 646 PetscFunctionReturn(0); 647 } 648 649 static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 650 { 651 DM_Plex *mesh = (DM_Plex*) dm->data; 652 DM cdm; 653 PetscSection coordSection; 654 Vec coordinates; 655 PetscViewerFormat format; 656 PetscErrorCode ierr; 657 658 PetscFunctionBegin; 659 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 660 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 661 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 662 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 663 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 664 const char *name; 665 PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 666 PetscInt pStart, pEnd, p, numLabels, l; 667 PetscMPIInt rank, size; 668 669 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 670 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 671 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 672 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 673 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 674 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 675 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 676 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 677 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 678 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 679 ierr = PetscViewerASCIIPrintf(viewer, "Supports:\n", name);CHKERRQ(ierr); 680 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 681 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize);CHKERRQ(ierr); 682 for (p = pStart; p < pEnd; ++p) { 683 PetscInt dof, off, s; 684 685 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 686 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 687 for (s = off; s < off+dof; ++s) { 688 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 689 } 690 } 691 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 692 ierr = PetscViewerASCIIPrintf(viewer, "Cones:\n", name);CHKERRQ(ierr); 693 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize);CHKERRQ(ierr); 694 for (p = pStart; p < pEnd; ++p) { 695 PetscInt dof, off, c; 696 697 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 698 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 699 for (c = off; c < off+dof; ++c) { 700 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 701 } 702 } 703 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 704 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 705 if (coordSection && coordinates) { 706 ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr); 707 } 708 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 709 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 710 for (l = 0; l < numLabels; ++l) { 711 DMLabel label; 712 PetscBool isdepth; 713 const char *name; 714 715 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 716 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 717 if (isdepth) continue; 718 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 719 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 720 } 721 if (size > 1) { 722 PetscSF sf; 723 724 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 725 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 726 } 727 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 728 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 729 const char *name, *color; 730 const char *defcolors[3] = {"gray", "orange", "green"}; 731 const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 732 char lname[PETSC_MAX_PATH_LEN]; 733 PetscReal scale = 2.0; 734 PetscReal tikzscale = 1.0; 735 PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 736 double tcoords[3]; 737 PetscScalar *coords; 738 PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 739 PetscMPIInt rank, size; 740 char **names, **colors, **lcolors; 741 PetscBool flg, lflg; 742 PetscBT wp = NULL; 743 PetscInt pEnd, pStart; 744 745 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 746 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 747 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 748 numLabels = PetscMax(numLabels, 10); 749 numColors = 10; 750 numLColors = 10; 751 ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 752 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 753 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL);CHKERRQ(ierr); 754 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 755 for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 756 for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 757 n = 4; 758 ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg);CHKERRQ(ierr); 759 if (flg && n != dim+1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 760 ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg);CHKERRQ(ierr); 761 if (flg && n != dim+1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 762 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 763 if (!useLabels) numLabels = 0; 764 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 765 if (!useColors) { 766 numColors = 3; 767 for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 768 } 769 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 770 if (!useColors) { 771 numLColors = 4; 772 for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 773 } 774 ierr = PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg);CHKERRQ(ierr); 775 plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 776 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg);CHKERRQ(ierr); 777 if (flg && plotEdges && depth < dim) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 778 if (depth < dim) plotEdges = PETSC_FALSE; 779 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL);CHKERRQ(ierr); 780 781 /* filter points with labelvalue != labeldefaultvalue */ 782 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 783 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 784 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 785 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 786 if (lflg) { 787 DMLabel lbl; 788 789 ierr = DMGetLabel(dm, lname, &lbl);CHKERRQ(ierr); 790 if (lbl) { 791 PetscInt val, defval; 792 793 ierr = DMLabelGetDefaultValue(lbl, &defval);CHKERRQ(ierr); 794 ierr = PetscBTCreate(pEnd-pStart, &wp);CHKERRQ(ierr); 795 for (c = pStart; c < pEnd; c++) { 796 PetscInt *closure = NULL; 797 PetscInt closureSize; 798 799 ierr = DMLabelGetValue(lbl, c, &val);CHKERRQ(ierr); 800 if (val == defval) continue; 801 802 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 803 for (p = 0; p < closureSize*2; p += 2) { 804 ierr = PetscBTSet(wp, closure[p] - pStart);CHKERRQ(ierr); 805 } 806 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 807 } 808 } 809 } 810 811 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 812 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 813 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 814 ierr = PetscViewerASCIIPrintf(viewer, "\ 815 \\documentclass[tikz]{standalone}\n\n\ 816 \\usepackage{pgflibraryshapes}\n\ 817 \\usetikzlibrary{backgrounds}\n\ 818 \\usetikzlibrary{arrows}\n\ 819 \\begin{document}\n");CHKERRQ(ierr); 820 if (size > 1) { 821 ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 822 for (p = 0; p < size; ++p) { 823 if (p > 0 && p == size-1) { 824 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 825 } else if (p > 0) { 826 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 827 } 828 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 829 } 830 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 831 } 832 if (drawHasse) { 833 PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart)); 834 835 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%D}\n", vStart);CHKERRQ(ierr); 836 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%D}\n", vEnd-1);CHKERRQ(ierr); 837 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%D}\n", vEnd-vStart);CHKERRQ(ierr); 838 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.);CHKERRQ(ierr); 839 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%D}\n", eStart);CHKERRQ(ierr); 840 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%D}\n", eEnd-1);CHKERRQ(ierr); 841 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.);CHKERRQ(ierr); 842 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%D}\n", eEnd-eStart);CHKERRQ(ierr); 843 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%D}\n", cStart);CHKERRQ(ierr); 844 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%D}\n", cEnd-1);CHKERRQ(ierr); 845 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%D}\n", cEnd-cStart);CHKERRQ(ierr); 846 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.);CHKERRQ(ierr); 847 } 848 ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale);CHKERRQ(ierr); 849 850 /* Plot vertices */ 851 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 852 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 853 for (v = vStart; v < vEnd; ++v) { 854 PetscInt off, dof, d; 855 PetscBool isLabeled = PETSC_FALSE; 856 857 if (wp && !PetscBTLookup(wp,v - pStart)) continue; 858 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 859 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 860 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 861 if (PetscUnlikely(dof > 3)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 862 for (d = 0; d < dof; ++d) { 863 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 864 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 865 } 866 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 867 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 868 for (d = 0; d < dof; ++d) { 869 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 870 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]);CHKERRQ(ierr); 871 } 872 if (drawHasse) color = colors[0%numColors]; 873 else color = colors[rank%numColors]; 874 for (l = 0; l < numLabels; ++l) { 875 PetscInt val; 876 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 877 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 878 } 879 if (drawNumbers[0]) { 880 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 881 } else if (drawColors[0]) { 882 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 883 } else { 884 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", v, rank);CHKERRQ(ierr); 885 } 886 } 887 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 888 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 889 /* Plot edges */ 890 if (plotEdges) { 891 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 892 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 893 for (e = eStart; e < eEnd; ++e) { 894 const PetscInt *cone; 895 PetscInt coneSize, offA, offB, dof, d; 896 897 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 898 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 899 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 900 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 901 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 902 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 903 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 904 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 905 for (d = 0; d < dof; ++d) { 906 tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 907 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 908 } 909 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 910 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 911 for (d = 0; d < dof; ++d) { 912 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 913 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr); 914 } 915 if (drawHasse) color = colors[1%numColors]; 916 else color = colors[rank%numColors]; 917 for (l = 0; l < numLabels; ++l) { 918 PetscInt val; 919 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 920 if (val >= 0) {color = lcolors[l%numLColors]; break;} 921 } 922 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 923 } 924 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 925 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 926 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 927 } 928 /* Plot cells */ 929 if (dim == 3 || !drawNumbers[1]) { 930 for (e = eStart; e < eEnd; ++e) { 931 const PetscInt *cone; 932 933 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 934 color = colors[rank%numColors]; 935 for (l = 0; l < numLabels; ++l) { 936 PetscInt val; 937 ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 938 if (val >= 0) {color = lcolors[l%numLColors]; break;} 939 } 940 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 941 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 942 } 943 } else { 944 DMPolytopeType ct; 945 946 /* Drawing a 2D polygon */ 947 for (c = cStart; c < cEnd; ++c) { 948 if (wp && !PetscBTLookup(wp, c - pStart)) continue; 949 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 950 if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || 951 ct == DM_POLYTOPE_TRI_PRISM_TENSOR || 952 ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 953 const PetscInt *cone; 954 PetscInt coneSize, e; 955 956 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 957 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 958 for (e = 0; e < coneSize; ++e) { 959 const PetscInt *econe; 960 961 ierr = DMPlexGetCone(dm, cone[e], &econe);CHKERRQ(ierr); 962 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); 963 } 964 } else { 965 PetscInt *closure = NULL; 966 PetscInt closureSize, Nv = 0, v; 967 968 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 969 for (p = 0; p < closureSize*2; p += 2) { 970 const PetscInt point = closure[p]; 971 972 if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 973 } 974 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 975 for (v = 0; v <= Nv; ++v) { 976 const PetscInt vertex = closure[v%Nv]; 977 978 if (v > 0) { 979 if (plotEdges) { 980 const PetscInt *edge; 981 PetscInt endpoints[2], ne; 982 983 endpoints[0] = closure[v-1]; endpoints[1] = vertex; 984 ierr = DMPlexGetJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr); 985 if (ne != 1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %D, %D", endpoints[0], endpoints[1]); 986 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d) -- ", edge[0], rank);CHKERRQ(ierr); 987 ierr = DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr); 988 } else { 989 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr); 990 } 991 } 992 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", vertex, rank);CHKERRQ(ierr); 993 } 994 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ";\n");CHKERRQ(ierr); 995 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 996 } 997 } 998 } 999 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1000 for (c = cStart; c < cEnd; ++c) { 1001 double ccoords[3] = {0.0, 0.0, 0.0}; 1002 PetscBool isLabeled = PETSC_FALSE; 1003 PetscInt *closure = NULL; 1004 PetscInt closureSize, dof, d, n = 0; 1005 1006 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 1007 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1008 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 1009 for (p = 0; p < closureSize*2; p += 2) { 1010 const PetscInt point = closure[p]; 1011 PetscInt off; 1012 1013 if ((point < vStart) || (point >= vEnd)) continue; 1014 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 1015 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 1016 for (d = 0; d < dof; ++d) { 1017 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1018 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1019 } 1020 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1021 if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1022 for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 1023 ++n; 1024 } 1025 for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 1026 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1027 for (d = 0; d < dof; ++d) { 1028 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 1029 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]);CHKERRQ(ierr); 1030 } 1031 if (drawHasse) color = colors[depth%numColors]; 1032 else color = colors[rank%numColors]; 1033 for (l = 0; l < numLabels; ++l) { 1034 PetscInt val; 1035 ierr = DMGetLabelValue(dm, names[l], c, &val);CHKERRQ(ierr); 1036 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 1037 } 1038 if (drawNumbers[dim]) { 1039 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c);CHKERRQ(ierr); 1040 } else if (drawColors[dim]) { 1041 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 1042 } else { 1043 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", c, rank);CHKERRQ(ierr); 1044 } 1045 } 1046 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1047 if (drawHasse) { 1048 color = colors[depth%numColors]; 1049 ierr = PetscViewerASCIIPrintf(viewer, "%% Cells\n");CHKERRQ(ierr); 1050 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n");CHKERRQ(ierr); 1051 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1052 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); 1053 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1054 1055 color = colors[1%numColors]; 1056 ierr = PetscViewerASCIIPrintf(viewer, "%% Edges\n");CHKERRQ(ierr); 1057 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n");CHKERRQ(ierr); 1058 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1059 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); 1060 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1061 1062 color = colors[0%numColors]; 1063 ierr = PetscViewerASCIIPrintf(viewer, "%% Vertices\n");CHKERRQ(ierr); 1064 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n");CHKERRQ(ierr); 1065 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1066 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); 1067 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1068 1069 for (p = pStart; p < pEnd; ++p) { 1070 const PetscInt *cone; 1071 PetscInt coneSize, cp; 1072 1073 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1074 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1075 for (cp = 0; cp < coneSize; ++cp) { 1076 ierr = PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%D_%d) -- (%D_%d);\n", cone[cp], rank, p, rank);CHKERRQ(ierr); 1077 } 1078 } 1079 } 1080 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1081 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 1082 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 1083 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 1084 for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 1085 for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 1086 for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 1087 ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 1088 ierr = PetscBTDestroy(&wp);CHKERRQ(ierr); 1089 } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 1090 Vec cown,acown; 1091 VecScatter sct; 1092 ISLocalToGlobalMapping g2l; 1093 IS gid,acis; 1094 MPI_Comm comm,ncomm = MPI_COMM_NULL; 1095 MPI_Group ggroup,ngroup; 1096 PetscScalar *array,nid; 1097 const PetscInt *idxs; 1098 PetscInt *idxs2,*start,*adjacency,*work; 1099 PetscInt64 lm[3],gm[3]; 1100 PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 1101 PetscMPIInt d1,d2,rank; 1102 1103 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1104 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 1105 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1106 ierr = MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm);CHKERRMPI(ierr); 1107 #endif 1108 if (ncomm != MPI_COMM_NULL) { 1109 ierr = MPI_Comm_group(comm,&ggroup);CHKERRMPI(ierr); 1110 ierr = MPI_Comm_group(ncomm,&ngroup);CHKERRMPI(ierr); 1111 d1 = 0; 1112 ierr = MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2);CHKERRMPI(ierr); 1113 nid = d2; 1114 ierr = MPI_Group_free(&ggroup);CHKERRMPI(ierr); 1115 ierr = MPI_Group_free(&ngroup);CHKERRMPI(ierr); 1116 ierr = MPI_Comm_free(&ncomm);CHKERRMPI(ierr); 1117 } else nid = 0.0; 1118 1119 /* Get connectivity */ 1120 ierr = DMPlexGetVTKCellHeight(dm,&cellHeight);CHKERRQ(ierr); 1121 ierr = DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid);CHKERRQ(ierr); 1122 1123 /* filter overlapped local cells */ 1124 ierr = DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd);CHKERRQ(ierr); 1125 ierr = ISGetIndices(gid,&idxs);CHKERRQ(ierr); 1126 ierr = ISGetLocalSize(gid,&cum);CHKERRQ(ierr); 1127 ierr = PetscMalloc1(cum,&idxs2);CHKERRQ(ierr); 1128 for (c = cStart, cum = 0; c < cEnd; c++) { 1129 if (idxs[c-cStart] < 0) continue; 1130 idxs2[cum++] = idxs[c-cStart]; 1131 } 1132 ierr = ISRestoreIndices(gid,&idxs);CHKERRQ(ierr); 1133 if (numVertices != cum) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum); 1134 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1135 ierr = ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid);CHKERRQ(ierr); 1136 1137 /* support for node-aware cell locality */ 1138 ierr = ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis);CHKERRQ(ierr); 1139 ierr = VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown);CHKERRQ(ierr); 1140 ierr = VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown);CHKERRQ(ierr); 1141 ierr = VecGetArray(cown,&array);CHKERRQ(ierr); 1142 for (c = 0; c < numVertices; c++) array[c] = nid; 1143 ierr = VecRestoreArray(cown,&array);CHKERRQ(ierr); 1144 ierr = VecScatterCreate(cown,acis,acown,NULL,&sct);CHKERRQ(ierr); 1145 ierr = VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1146 ierr = VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1147 ierr = ISDestroy(&acis);CHKERRQ(ierr); 1148 ierr = VecScatterDestroy(&sct);CHKERRQ(ierr); 1149 ierr = VecDestroy(&cown);CHKERRQ(ierr); 1150 1151 /* compute edgeCut */ 1152 for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 1153 ierr = PetscMalloc1(cum,&work);CHKERRQ(ierr); 1154 ierr = ISLocalToGlobalMappingCreateIS(gid,&g2l);CHKERRQ(ierr); 1155 ierr = ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 1156 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1157 ierr = VecGetArray(acown,&array);CHKERRQ(ierr); 1158 for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 1159 PetscInt totl; 1160 1161 totl = start[c+1]-start[c]; 1162 ierr = ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work);CHKERRQ(ierr); 1163 for (i = 0; i < totl; i++) { 1164 if (work[i] < 0) { 1165 ect += 1; 1166 ectn += (array[i + start[c]] != nid) ? 0 : 1; 1167 } 1168 } 1169 } 1170 ierr = PetscFree(work);CHKERRQ(ierr); 1171 ierr = VecRestoreArray(acown,&array);CHKERRQ(ierr); 1172 lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 1173 lm[1] = -numVertices; 1174 ierr = MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm);CHKERRMPI(ierr); 1175 ierr = PetscViewerASCIIPrintf(viewer," Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]);CHKERRQ(ierr); 1176 lm[0] = ect; /* edgeCut */ 1177 lm[1] = ectn; /* node-aware edgeCut */ 1178 lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 1179 ierr = MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr); 1180 ierr = PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]);CHKERRQ(ierr); 1181 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1182 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); 1183 #else 1184 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0);CHKERRQ(ierr); 1185 #endif 1186 ierr = ISLocalToGlobalMappingDestroy(&g2l);CHKERRQ(ierr); 1187 ierr = PetscFree(start);CHKERRQ(ierr); 1188 ierr = PetscFree(adjacency);CHKERRQ(ierr); 1189 ierr = VecDestroy(&acown);CHKERRQ(ierr); 1190 } else { 1191 const char *name; 1192 PetscInt *sizes, *hybsizes, *ghostsizes; 1193 PetscInt locDepth, depth, cellHeight, dim, d; 1194 PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1195 PetscInt numLabels, l; 1196 DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1197 MPI_Comm comm; 1198 PetscMPIInt size, rank; 1199 1200 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1201 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1202 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1203 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1204 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 1205 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 1206 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1207 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1208 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 1209 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 1210 ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRMPI(ierr); 1211 ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr); 1212 gcNum = gcEnd - gcStart; 1213 ierr = PetscCalloc3(size,&sizes,size,&hybsizes,size,&ghostsizes);CHKERRQ(ierr); 1214 for (d = 0; d <= depth; d++) { 1215 PetscInt Nc[2] = {0, 0}, ict; 1216 1217 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 1218 if (pStart < pEnd) {ierr = DMPlexGetCellType(dm, pStart, &ct0);CHKERRQ(ierr);} 1219 ict = ct0; 1220 ierr = MPI_Bcast(&ict, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1221 ct0 = (DMPolytopeType) ict; 1222 for (p = pStart; p < pEnd; ++p) { 1223 DMPolytopeType ct; 1224 1225 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 1226 if (ct == ct0) ++Nc[0]; 1227 else ++Nc[1]; 1228 } 1229 ierr = MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1230 ierr = MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1231 if (d == depth) {ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);} 1232 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", (depth == 1) && d ? dim : d);CHKERRQ(ierr); 1233 for (p = 0; p < size; ++p) { 1234 if (rank == 0) { 1235 ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]);CHKERRQ(ierr); 1236 if (hybsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]);CHKERRQ(ierr);} 1237 if (ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);} 1238 } 1239 } 1240 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 1241 } 1242 ierr = PetscFree3(sizes,hybsizes,ghostsizes);CHKERRQ(ierr); 1243 { 1244 const PetscReal *maxCell; 1245 const PetscReal *L; 1246 const DMBoundaryType *bd; 1247 PetscBool per, localized; 1248 1249 ierr = DMGetPeriodicity(dm, &per, &maxCell, &L, &bd);CHKERRQ(ierr); 1250 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 1251 if (per) { 1252 ierr = PetscViewerASCIIPrintf(viewer, "Periodic mesh (");CHKERRQ(ierr); 1253 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1254 for (d = 0; d < dim; ++d) { 1255 if (bd && d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1256 if (bd) {ierr = PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]]);CHKERRQ(ierr);} 1257 } 1258 ierr = PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized");CHKERRQ(ierr); 1259 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1260 } 1261 } 1262 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 1263 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 1264 for (l = 0; l < numLabels; ++l) { 1265 DMLabel label; 1266 const char *name; 1267 IS valueIS; 1268 const PetscInt *values; 1269 PetscInt numValues, v; 1270 1271 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 1272 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1273 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 1274 ierr = PetscViewerASCIIPrintf(viewer, " %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr); 1275 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 1276 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 1277 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1278 for (v = 0; v < numValues; ++v) { 1279 PetscInt size; 1280 1281 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 1282 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1283 ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr); 1284 } 1285 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 1286 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1287 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 1288 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 1289 } 1290 { 1291 char **labelNames; 1292 PetscInt Nl = numLabels; 1293 PetscBool flg; 1294 1295 ierr = PetscMalloc1(Nl, &labelNames);CHKERRQ(ierr); 1296 ierr = PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg);CHKERRQ(ierr); 1297 for (l = 0; l < Nl; ++l) { 1298 DMLabel label; 1299 1300 ierr = DMHasLabel(dm, labelNames[l], &flg);CHKERRQ(ierr); 1301 if (flg) { 1302 ierr = DMGetLabel(dm, labelNames[l], &label);CHKERRQ(ierr); 1303 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 1304 } 1305 ierr = PetscFree(labelNames[l]);CHKERRQ(ierr); 1306 } 1307 ierr = PetscFree(labelNames);CHKERRQ(ierr); 1308 } 1309 /* If no fields are specified, people do not want to see adjacency */ 1310 if (dm->Nf) { 1311 PetscInt f; 1312 1313 for (f = 0; f < dm->Nf; ++f) { 1314 const char *name; 1315 1316 ierr = PetscObjectGetName(dm->fields[f].disc, &name);CHKERRQ(ierr); 1317 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Field %s:\n", name);CHKERRQ(ierr);} 1318 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1319 if (dm->fields[f].label) {ierr = DMLabelView(dm->fields[f].label, viewer);CHKERRQ(ierr);} 1320 if (dm->fields[f].adjacency[0]) { 1321 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n");CHKERRQ(ierr);} 1322 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM\n");CHKERRQ(ierr);} 1323 } else { 1324 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FEM\n");CHKERRQ(ierr);} 1325 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n");CHKERRQ(ierr);} 1326 } 1327 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1328 } 1329 } 1330 ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr); 1331 if (cdm) { 1332 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1333 ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr); 1334 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1335 } 1336 } 1337 PetscFunctionReturn(0); 1338 } 1339 1340 static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1341 { 1342 DMPolytopeType ct; 1343 PetscMPIInt rank; 1344 PetscErrorCode ierr; 1345 1346 PetscFunctionBegin; 1347 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1348 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1349 switch (ct) { 1350 case DM_POLYTOPE_TRIANGLE: 1351 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1352 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1353 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1354 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1355 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1356 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1357 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1358 break; 1359 case DM_POLYTOPE_QUADRILATERAL: 1360 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1361 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1362 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1363 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1364 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1365 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1366 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1367 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1368 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1369 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1370 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1371 ierr = PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1372 break; 1373 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1374 } 1375 PetscFunctionReturn(0); 1376 } 1377 1378 static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1379 { 1380 DMPolytopeType ct; 1381 PetscReal centroid[2] = {0., 0.}; 1382 PetscMPIInt rank; 1383 PetscInt fillColor, v, e, d; 1384 PetscErrorCode ierr; 1385 1386 PetscFunctionBegin; 1387 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1388 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1389 fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2; 1390 switch (ct) { 1391 case DM_POLYTOPE_TRIANGLE: 1392 { 1393 PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1394 1395 for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;} 1396 for (e = 0; e < 3; ++e) { 1397 refCoords[0] = refVertices[e*2+0]; 1398 refCoords[1] = refVertices[e*2+1]; 1399 for (d = 1; d <= edgeDiv; ++d) { 1400 refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv; 1401 refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv; 1402 } 1403 ierr = DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords);CHKERRQ(ierr); 1404 for (d = 0; d < edgeDiv; ++d) { 1405 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); 1406 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); 1407 } 1408 } 1409 } 1410 break; 1411 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1412 } 1413 PetscFunctionReturn(0); 1414 } 1415 1416 static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1417 { 1418 PetscDraw draw; 1419 DM cdm; 1420 PetscSection coordSection; 1421 Vec coordinates; 1422 const PetscScalar *coords; 1423 PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1424 PetscReal *refCoords, *edgeCoords; 1425 PetscBool isnull, drawAffine = PETSC_TRUE; 1426 PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1427 PetscErrorCode ierr; 1428 1429 PetscFunctionBegin; 1430 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 1431 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim); 1432 ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL);CHKERRQ(ierr); 1433 if (!drawAffine) {ierr = PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords);CHKERRQ(ierr);} 1434 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 1435 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1436 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 1437 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1438 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1439 1440 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 1441 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 1442 if (isnull) PetscFunctionReturn(0); 1443 ierr = PetscDrawSetTitle(draw, "Mesh");CHKERRQ(ierr); 1444 1445 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 1446 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 1447 for (c = 0; c < N; c += dim) { 1448 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 1449 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1450 } 1451 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 1452 ierr = MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1453 ierr = MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1454 ierr = PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]);CHKERRQ(ierr); 1455 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 1456 1457 for (c = cStart; c < cEnd; ++c) { 1458 PetscScalar *coords = NULL; 1459 PetscInt numCoords; 1460 1461 ierr = DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords);CHKERRQ(ierr); 1462 if (drawAffine) { 1463 ierr = DMPlexDrawCell(dm, draw, c, coords);CHKERRQ(ierr); 1464 } else { 1465 ierr = DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords);CHKERRQ(ierr); 1466 } 1467 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 1468 } 1469 if (!drawAffine) {ierr = PetscFree2(refCoords, edgeCoords);CHKERRQ(ierr);} 1470 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1471 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 1472 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 1473 PetscFunctionReturn(0); 1474 } 1475 1476 #if defined(PETSC_HAVE_EXODUSII) 1477 #include <exodusII.h> 1478 #include <petscviewerexodusii.h> 1479 #endif 1480 1481 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1482 { 1483 PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1484 char name[PETSC_MAX_PATH_LEN]; 1485 PetscErrorCode ierr; 1486 1487 PetscFunctionBegin; 1488 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1489 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1490 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1491 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1492 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1493 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 1494 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 1495 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus);CHKERRQ(ierr); 1496 if (iascii) { 1497 PetscViewerFormat format; 1498 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1499 if (format == PETSC_VIEWER_ASCII_GLVIS) { 1500 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1501 } else { 1502 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 1503 } 1504 } else if (ishdf5) { 1505 #if defined(PETSC_HAVE_HDF5) 1506 ierr = DMPlexView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1507 #else 1508 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1509 #endif 1510 } else if (isvtk) { 1511 ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr); 1512 } else if (isdraw) { 1513 ierr = DMPlexView_Draw(dm, viewer);CHKERRQ(ierr); 1514 } else if (isglvis) { 1515 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1516 #if defined(PETSC_HAVE_EXODUSII) 1517 } else if (isexodus) { 1518 /* 1519 exodusII requires that all sets be part of exactly one cell set. 1520 If the dm does not have a "Cell Sets" label defined, we create one 1521 with ID 1, containig all cells. 1522 Note that if the Cell Sets label is defined but does not cover all cells, 1523 we may still have a problem. This should probably be checked here or in the viewer; 1524 */ 1525 PetscInt numCS; 1526 ierr = DMGetLabelSize(dm,"Cell Sets",&numCS);CHKERRQ(ierr); 1527 if (!numCS) { 1528 PetscInt cStart, cEnd, c; 1529 ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr); 1530 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1531 for (c = cStart; c < cEnd; ++c) {ierr = DMSetLabelValue(dm, "Cell Sets", c, 1);CHKERRQ(ierr);} 1532 } 1533 ierr = DMView_PlexExodusII(dm, viewer);CHKERRQ(ierr); 1534 #endif 1535 } else { 1536 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1537 } 1538 /* Optionally view the partition */ 1539 ierr = PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg);CHKERRQ(ierr); 1540 if (flg) { 1541 Vec ranks; 1542 ierr = DMPlexCreateRankField(dm, &ranks);CHKERRQ(ierr); 1543 ierr = VecView(ranks, viewer);CHKERRQ(ierr); 1544 ierr = VecDestroy(&ranks);CHKERRQ(ierr); 1545 } 1546 /* Optionally view a label */ 1547 ierr = PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg);CHKERRQ(ierr); 1548 if (flg) { 1549 DMLabel label; 1550 Vec val; 1551 1552 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1553 if (!label) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 1554 ierr = DMPlexCreateLabelField(dm, label, &val);CHKERRQ(ierr); 1555 ierr = VecView(val, viewer);CHKERRQ(ierr); 1556 ierr = VecDestroy(&val);CHKERRQ(ierr); 1557 } 1558 PetscFunctionReturn(0); 1559 } 1560 1561 /*@ 1562 DMPlexTopologyView - Saves a DMPlex topology into a file 1563 1564 Collective on DM 1565 1566 Input Parameters: 1567 + dm - The DM whose topology is to be saved 1568 - viewer - The PetscViewer for saving 1569 1570 Level: advanced 1571 1572 .seealso: DMView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexTopologyLoad() 1573 @*/ 1574 PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 1575 { 1576 PetscBool ishdf5; 1577 PetscErrorCode ierr; 1578 1579 PetscFunctionBegin; 1580 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1581 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1582 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1583 if (ishdf5) { 1584 #if defined(PETSC_HAVE_HDF5) 1585 PetscViewerFormat format; 1586 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1587 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1588 IS globalPointNumbering; 1589 1590 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1591 ierr = DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1592 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1593 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 1594 #else 1595 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1596 #endif 1597 } 1598 PetscFunctionReturn(0); 1599 } 1600 1601 /*@ 1602 DMPlexCoordinatesView - Saves DMPlex coordinates into a file 1603 1604 Collective on DM 1605 1606 Input Parameters: 1607 + dm - The DM whose coordinates are to be saved 1608 - viewer - The PetscViewer for saving 1609 1610 Level: advanced 1611 1612 .seealso: DMView(), DMPlexTopologyView(), DMPlexLabelsView(), DMPlexCoordinatesLoad() 1613 @*/ 1614 PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 1615 { 1616 PetscBool ishdf5; 1617 PetscErrorCode ierr; 1618 1619 PetscFunctionBegin; 1620 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1621 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1622 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1623 if (ishdf5) { 1624 #if defined(PETSC_HAVE_HDF5) 1625 PetscViewerFormat format; 1626 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1627 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1628 ierr = DMPlexCoordinatesView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1629 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1630 #else 1631 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1632 #endif 1633 } 1634 PetscFunctionReturn(0); 1635 } 1636 1637 /*@ 1638 DMPlexLabelsView - Saves DMPlex labels into a file 1639 1640 Collective on DM 1641 1642 Input Parameters: 1643 + dm - The DM whose labels are to be saved 1644 - viewer - The PetscViewer for saving 1645 1646 Level: advanced 1647 1648 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsLoad() 1649 @*/ 1650 PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1651 { 1652 PetscBool ishdf5; 1653 PetscErrorCode ierr; 1654 1655 PetscFunctionBegin; 1656 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1657 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1658 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1659 if (ishdf5) { 1660 #if defined(PETSC_HAVE_HDF5) 1661 IS globalPointNumbering; 1662 PetscViewerFormat format; 1663 1664 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1665 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1666 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1667 ierr = DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1668 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1669 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1670 #else 1671 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1672 #endif 1673 } 1674 PetscFunctionReturn(0); 1675 } 1676 1677 /*@ 1678 DMPlexSectionView - Saves a section associated with a DMPlex 1679 1680 Collective on DM 1681 1682 Input Parameters: 1683 + dm - The DM that contains the topology on which the section to be saved is defined 1684 . viewer - The PetscViewer for saving 1685 - sectiondm - The DM that contains the section to be saved 1686 1687 Level: advanced 1688 1689 Notes: 1690 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. 1691 1692 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. 1693 1694 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexGlobalVectorView(), DMPlexLocalVectorView(), PetscSectionView(), DMPlexSectionLoad() 1695 @*/ 1696 PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1697 { 1698 PetscBool ishdf5; 1699 PetscErrorCode ierr; 1700 1701 PetscFunctionBegin; 1702 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1703 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1704 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1705 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 1706 if (ishdf5) { 1707 #if defined(PETSC_HAVE_HDF5) 1708 ierr = DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm);CHKERRQ(ierr); 1709 #else 1710 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1711 #endif 1712 } 1713 PetscFunctionReturn(0); 1714 } 1715 1716 /*@ 1717 DMPlexGlobalVectorView - Saves a global vector 1718 1719 Collective on DM 1720 1721 Input Parameters: 1722 + dm - The DM that represents the topology 1723 . viewer - The PetscViewer to save data with 1724 . sectiondm - The DM that contains the global section on which vec is defined 1725 - vec - The global vector to be saved 1726 1727 Level: advanced 1728 1729 Notes: 1730 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. 1731 1732 Typical calling sequence 1733 $ DMCreate(PETSC_COMM_WORLD, &dm); 1734 $ DMSetType(dm, DMPLEX); 1735 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1736 $ DMClone(dm, §iondm); 1737 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1738 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1739 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1740 $ PetscSectionSetChart(section, pStart, pEnd); 1741 $ PetscSectionSetUp(section); 1742 $ DMSetLocalSection(sectiondm, section); 1743 $ PetscSectionDestroy(§ion); 1744 $ DMGetGlobalVector(sectiondm, &vec); 1745 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1746 $ DMPlexTopologyView(dm, viewer); 1747 $ DMPlexSectionView(dm, viewer, sectiondm); 1748 $ DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 1749 $ DMRestoreGlobalVector(sectiondm, &vec); 1750 $ DMDestroy(§iondm); 1751 $ DMDestroy(&dm); 1752 1753 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexLocalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1754 @*/ 1755 PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1756 { 1757 PetscBool ishdf5; 1758 PetscErrorCode ierr; 1759 1760 PetscFunctionBegin; 1761 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1762 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1763 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1764 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1765 /* Check consistency */ 1766 { 1767 PetscSection section; 1768 PetscBool includesConstraints; 1769 PetscInt m, m1; 1770 1771 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1772 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 1773 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1774 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1775 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1776 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 1777 } 1778 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1779 if (ishdf5) { 1780 #if defined(PETSC_HAVE_HDF5) 1781 ierr = DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1782 #else 1783 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1784 #endif 1785 } 1786 PetscFunctionReturn(0); 1787 } 1788 1789 /*@ 1790 DMPlexLocalVectorView - Saves a local vector 1791 1792 Collective on DM 1793 1794 Input Parameters: 1795 + dm - The DM that represents the topology 1796 . viewer - The PetscViewer to save data with 1797 . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm 1798 - vec - The local vector to be saved 1799 1800 Level: advanced 1801 1802 Notes: 1803 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. 1804 1805 Typical calling sequence 1806 $ DMCreate(PETSC_COMM_WORLD, &dm); 1807 $ DMSetType(dm, DMPLEX); 1808 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1809 $ DMClone(dm, §iondm); 1810 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1811 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1812 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1813 $ PetscSectionSetChart(section, pStart, pEnd); 1814 $ PetscSectionSetUp(section); 1815 $ DMSetLocalSection(sectiondm, section); 1816 $ DMGetLocalVector(sectiondm, &vec); 1817 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1818 $ DMPlexTopologyView(dm, viewer); 1819 $ DMPlexSectionView(dm, viewer, sectiondm); 1820 $ DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 1821 $ DMRestoreLocalVector(sectiondm, &vec); 1822 $ DMDestroy(§iondm); 1823 $ DMDestroy(&dm); 1824 1825 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexGlobalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1826 @*/ 1827 PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1828 { 1829 PetscBool ishdf5; 1830 PetscErrorCode ierr; 1831 1832 PetscFunctionBegin; 1833 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1834 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1835 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1836 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1837 /* Check consistency */ 1838 { 1839 PetscSection section; 1840 PetscBool includesConstraints; 1841 PetscInt m, m1; 1842 1843 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1844 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 1845 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1846 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1847 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1848 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 1849 } 1850 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1851 if (ishdf5) { 1852 #if defined(PETSC_HAVE_HDF5) 1853 ierr = DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1854 #else 1855 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1856 #endif 1857 } 1858 PetscFunctionReturn(0); 1859 } 1860 1861 PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 1862 { 1863 PetscBool ishdf5; 1864 PetscErrorCode ierr; 1865 1866 PetscFunctionBegin; 1867 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1868 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1869 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1870 if (ishdf5) { 1871 #if defined(PETSC_HAVE_HDF5) 1872 PetscViewerFormat format; 1873 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1874 if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 1875 ierr = DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer);CHKERRQ(ierr); 1876 } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1877 ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1878 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1879 PetscFunctionReturn(0); 1880 #else 1881 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1882 #endif 1883 } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 1884 } 1885 1886 /*@ 1887 DMPlexTopologyLoad - Loads a topology into a DMPlex 1888 1889 Collective on DM 1890 1891 Input Parameters: 1892 + dm - The DM into which the topology is loaded 1893 - viewer - The PetscViewer for the saved topology 1894 1895 Output Parameters: 1896 . 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 1897 1898 Level: advanced 1899 1900 .seealso: DMLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1901 @*/ 1902 PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 1903 { 1904 PetscBool ishdf5; 1905 PetscErrorCode ierr; 1906 1907 PetscFunctionBegin; 1908 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1909 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1910 if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 1911 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1912 if (ishdf5) { 1913 #if defined(PETSC_HAVE_HDF5) 1914 PetscViewerFormat format; 1915 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1916 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1917 ierr = DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 1918 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1919 #else 1920 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1921 #endif 1922 } 1923 PetscFunctionReturn(0); 1924 } 1925 1926 /*@ 1927 DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 1928 1929 Collective on DM 1930 1931 Input Parameters: 1932 + dm - The DM into which the coordinates are loaded 1933 - viewer - The PetscViewer for the saved coordinates 1934 1935 Level: advanced 1936 1937 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1938 @*/ 1939 PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer) 1940 { 1941 PetscBool ishdf5; 1942 PetscErrorCode ierr; 1943 1944 PetscFunctionBegin; 1945 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1946 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1947 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1948 if (ishdf5) { 1949 #if defined(PETSC_HAVE_HDF5) 1950 PetscViewerFormat format; 1951 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1952 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1953 ierr = DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1954 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1955 #else 1956 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1957 #endif 1958 } 1959 PetscFunctionReturn(0); 1960 } 1961 1962 /*@ 1963 DMPlexLabelsLoad - Loads labels into a DMPlex 1964 1965 Collective on DM 1966 1967 Input Parameters: 1968 + dm - The DM into which the labels are loaded 1969 - viewer - The PetscViewer for the saved labels 1970 1971 Level: advanced 1972 1973 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1974 @*/ 1975 PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer) 1976 { 1977 PetscBool ishdf5; 1978 PetscErrorCode ierr; 1979 1980 PetscFunctionBegin; 1981 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1982 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1983 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1984 if (ishdf5) { 1985 #if defined(PETSC_HAVE_HDF5) 1986 PetscViewerFormat format; 1987 1988 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1989 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1990 ierr = DMPlexLabelsLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1991 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1992 #else 1993 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1994 #endif 1995 } 1996 PetscFunctionReturn(0); 1997 } 1998 1999 /*@ 2000 DMPlexSectionLoad - Loads section into a DMPlex 2001 2002 Collective on DM 2003 2004 Input Parameters: 2005 + dm - The DM that represents the topology 2006 . viewer - The PetscViewer that represents the on-disk section (sectionA) 2007 . sectiondm - The DM into which the on-disk section (sectionA) is migrated 2008 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2009 2010 Output Parameters 2011 + 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) 2012 - 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) 2013 2014 Level: advanced 2015 2016 Notes: 2017 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. 2018 2019 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. 2020 2021 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. 2022 2023 Example using 2 processes: 2024 $ NX (number of points on dm): 4 2025 $ sectionA : the on-disk section 2026 $ vecA : a vector associated with sectionA 2027 $ sectionB : sectiondm's local section constructed in this function 2028 $ vecB (local) : a vector associated with sectiondm's local section 2029 $ vecB (global) : a vector associated with sectiondm's global section 2030 $ 2031 $ rank 0 rank 1 2032 $ vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2033 $ sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2034 $ sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2035 $ sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2036 $ [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2037 $ sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2038 $ sectionB->atlasDof : 1 0 1 | 1 3 2039 $ sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2040 $ vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2041 $ vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2042 $ 2043 $ where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2044 2045 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad(), PetscSectionLoad(), DMPlexSectionView() 2046 @*/ 2047 PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2048 { 2049 PetscBool ishdf5; 2050 PetscErrorCode ierr; 2051 2052 PetscFunctionBegin; 2053 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2054 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2055 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2056 PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 2057 if (globalDofSF) PetscValidPointer(globalDofSF, 5); 2058 if (localDofSF) PetscValidPointer(localDofSF, 6); 2059 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2060 if (ishdf5) { 2061 #if defined(PETSC_HAVE_HDF5) 2062 ierr = DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF);CHKERRQ(ierr); 2063 #else 2064 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2065 #endif 2066 } 2067 PetscFunctionReturn(0); 2068 } 2069 2070 /*@ 2071 DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 2072 2073 Collective on DM 2074 2075 Input Parameters: 2076 + dm - The DM that represents the topology 2077 . viewer - The PetscViewer that represents the on-disk vector data 2078 . sectiondm - The DM that contains the global section on which vec is defined 2079 . sf - The SF that migrates the on-disk vector data into vec 2080 - vec - The global vector to set values of 2081 2082 Level: advanced 2083 2084 Notes: 2085 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. 2086 2087 Typical calling sequence 2088 $ DMCreate(PETSC_COMM_WORLD, &dm); 2089 $ DMSetType(dm, DMPLEX); 2090 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2091 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2092 $ DMClone(dm, §iondm); 2093 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2094 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2095 $ DMGetGlobalVector(sectiondm, &vec); 2096 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2097 $ DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2098 $ DMRestoreGlobalVector(sectiondm, &vec); 2099 $ PetscSFDestroy(&gsf); 2100 $ PetscSFDestroy(&sfX); 2101 $ DMDestroy(§iondm); 2102 $ DMDestroy(&dm); 2103 2104 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexLocalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2105 @*/ 2106 PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2107 { 2108 PetscBool ishdf5; 2109 PetscErrorCode ierr; 2110 2111 PetscFunctionBegin; 2112 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2113 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2114 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2115 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2116 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2117 /* Check consistency */ 2118 { 2119 PetscSection section; 2120 PetscBool includesConstraints; 2121 PetscInt m, m1; 2122 2123 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2124 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 2125 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2126 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2127 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2128 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 2129 } 2130 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2131 if (ishdf5) { 2132 #if defined(PETSC_HAVE_HDF5) 2133 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2134 #else 2135 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2136 #endif 2137 } 2138 PetscFunctionReturn(0); 2139 } 2140 2141 /*@ 2142 DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 2143 2144 Collective on DM 2145 2146 Input Parameters: 2147 + dm - The DM that represents the topology 2148 . viewer - The PetscViewer that represents the on-disk vector data 2149 . sectiondm - The DM that contains the local section on which vec is defined 2150 . sf - The SF that migrates the on-disk vector data into vec 2151 - vec - The local vector to set values of 2152 2153 Level: advanced 2154 2155 Notes: 2156 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. 2157 2158 Typical calling sequence 2159 $ DMCreate(PETSC_COMM_WORLD, &dm); 2160 $ DMSetType(dm, DMPLEX); 2161 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2162 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2163 $ DMClone(dm, §iondm); 2164 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2165 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2166 $ DMGetLocalVector(sectiondm, &vec); 2167 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2168 $ DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2169 $ DMRestoreLocalVector(sectiondm, &vec); 2170 $ PetscSFDestroy(&lsf); 2171 $ PetscSFDestroy(&sfX); 2172 $ DMDestroy(§iondm); 2173 $ DMDestroy(&dm); 2174 2175 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexGlobalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2176 @*/ 2177 PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2178 { 2179 PetscBool ishdf5; 2180 PetscErrorCode ierr; 2181 2182 PetscFunctionBegin; 2183 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2184 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2185 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2186 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2187 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2188 /* Check consistency */ 2189 { 2190 PetscSection section; 2191 PetscBool includesConstraints; 2192 PetscInt m, m1; 2193 2194 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2195 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 2196 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2197 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2198 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2199 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 2200 } 2201 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2202 if (ishdf5) { 2203 #if defined(PETSC_HAVE_HDF5) 2204 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2205 #else 2206 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2207 #endif 2208 } 2209 PetscFunctionReturn(0); 2210 } 2211 2212 PetscErrorCode DMDestroy_Plex(DM dm) 2213 { 2214 DM_Plex *mesh = (DM_Plex*) dm->data; 2215 PetscErrorCode ierr; 2216 2217 PetscFunctionBegin; 2218 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr); 2219 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr); 2220 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL);CHKERRQ(ierr); 2221 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL);CHKERRQ(ierr); 2222 if (--mesh->refct > 0) PetscFunctionReturn(0); 2223 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 2224 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 2225 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 2226 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 2227 ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr); 2228 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 2229 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 2230 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 2231 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 2232 ierr = PetscFree(mesh->transformType);CHKERRQ(ierr); 2233 ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 2234 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 2235 ierr = ISDestroy(&mesh->subpointIS);CHKERRQ(ierr); 2236 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 2237 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 2238 ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 2239 ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 2240 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 2241 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 2242 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 2243 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 2244 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 2245 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 2246 ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr); 2247 ierr = PetscFree(mesh->neighbors);CHKERRQ(ierr); 2248 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 2249 ierr = PetscFree(mesh);CHKERRQ(ierr); 2250 PetscFunctionReturn(0); 2251 } 2252 2253 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2254 { 2255 PetscSection sectionGlobal; 2256 PetscInt bs = -1, mbs; 2257 PetscInt localSize; 2258 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2259 PetscErrorCode ierr; 2260 MatType mtype; 2261 ISLocalToGlobalMapping ltog; 2262 2263 PetscFunctionBegin; 2264 ierr = MatInitializePackage();CHKERRQ(ierr); 2265 mtype = dm->mattype; 2266 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 2267 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 2268 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 2269 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 2270 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 2271 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 2272 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 2273 ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr); 2274 if (mbs > 1) bs = mbs; 2275 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 2276 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 2277 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 2278 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 2279 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 2280 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 2281 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 2282 ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr); 2283 if (!isShell) { 2284 PetscSection subSection; 2285 PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 2286 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *ltogidx, lsize; 2287 PetscInt pStart, pEnd, p, dof, cdof; 2288 2289 /* Set localtoglobalmapping on the matrix for MatSetValuesLocal() to work (it also creates the local matrices in case of MATIS) */ 2290 if (isMatIS) { /* need a different l2g map than the one computed by DMGetLocalToGlobalMapping */ 2291 PetscSection section; 2292 PetscInt size; 2293 2294 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 2295 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 2296 ierr = PetscMalloc1(size,<ogidx);CHKERRQ(ierr); 2297 ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr); 2298 } else { 2299 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 2300 } 2301 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 2302 for (p = pStart, lsize = 0; p < pEnd; ++p) { 2303 PetscInt bdof; 2304 2305 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 2306 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 2307 dof = dof < 0 ? -(dof+1) : dof; 2308 bdof = cdof && (dof-cdof) ? 1 : dof; 2309 if (dof) { 2310 if (bs < 0) {bs = bdof;} 2311 else if (bs != bdof) {bs = 1; if (!isMatIS) break;} 2312 } 2313 if (isMatIS) { 2314 PetscInt loff,c,off; 2315 ierr = PetscSectionGetOffset(subSection, p, &loff);CHKERRQ(ierr); 2316 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 2317 for (c = 0; c < dof-cdof; ++c, ++lsize) ltogidx[loff+c] = off > -1 ? off+c : -(off+1)+c; 2318 } 2319 } 2320 /* Must have same blocksize on all procs (some might have no points) */ 2321 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 2322 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 2323 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 2324 else {bs = bsMinMax[0];} 2325 bs = PetscMax(1,bs); 2326 if (isMatIS) { /* Must reduce indices by blocksize */ 2327 PetscInt l; 2328 2329 lsize = lsize/bs; 2330 if (bs > 1) for (l = 0; l < lsize; ++l) ltogidx[l] = ltogidx[l*bs]/bs; 2331 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, lsize, ltogidx, PETSC_OWN_POINTER, <og);CHKERRQ(ierr); 2332 } 2333 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 2334 if (isMatIS) { 2335 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 2336 } 2337 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 2338 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 2339 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 2340 } 2341 ierr = MatSetDM(*J, dm);CHKERRQ(ierr); 2342 PetscFunctionReturn(0); 2343 } 2344 2345 /*@ 2346 DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2347 2348 Not collective 2349 2350 Input Parameter: 2351 . mesh - The DMPlex 2352 2353 Output Parameters: 2354 . subsection - The subdomain section 2355 2356 Level: developer 2357 2358 .seealso: 2359 @*/ 2360 PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2361 { 2362 DM_Plex *mesh = (DM_Plex*) dm->data; 2363 PetscErrorCode ierr; 2364 2365 PetscFunctionBegin; 2366 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2367 if (!mesh->subdomainSection) { 2368 PetscSection section; 2369 PetscSF sf; 2370 2371 ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr); 2372 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 2373 ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr); 2374 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 2375 } 2376 *subsection = mesh->subdomainSection; 2377 PetscFunctionReturn(0); 2378 } 2379 2380 /*@ 2381 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2382 2383 Not collective 2384 2385 Input Parameter: 2386 . mesh - The DMPlex 2387 2388 Output Parameters: 2389 + pStart - The first mesh point 2390 - pEnd - The upper bound for mesh points 2391 2392 Level: beginner 2393 2394 .seealso: DMPlexCreate(), DMPlexSetChart() 2395 @*/ 2396 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2397 { 2398 DM_Plex *mesh = (DM_Plex*) dm->data; 2399 PetscErrorCode ierr; 2400 2401 PetscFunctionBegin; 2402 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2403 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2404 PetscFunctionReturn(0); 2405 } 2406 2407 /*@ 2408 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2409 2410 Not collective 2411 2412 Input Parameters: 2413 + mesh - The DMPlex 2414 . pStart - The first mesh point 2415 - pEnd - The upper bound for mesh points 2416 2417 Output Parameters: 2418 2419 Level: beginner 2420 2421 .seealso: DMPlexCreate(), DMPlexGetChart() 2422 @*/ 2423 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2424 { 2425 DM_Plex *mesh = (DM_Plex*) dm->data; 2426 PetscErrorCode ierr; 2427 2428 PetscFunctionBegin; 2429 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2430 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2431 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 2432 PetscFunctionReturn(0); 2433 } 2434 2435 /*@ 2436 DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2437 2438 Not collective 2439 2440 Input Parameters: 2441 + mesh - The DMPlex 2442 - p - The point, which must lie in the chart set with DMPlexSetChart() 2443 2444 Output Parameter: 2445 . size - The cone size for point p 2446 2447 Level: beginner 2448 2449 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2450 @*/ 2451 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2452 { 2453 DM_Plex *mesh = (DM_Plex*) dm->data; 2454 PetscErrorCode ierr; 2455 2456 PetscFunctionBegin; 2457 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2458 PetscValidPointer(size, 3); 2459 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2460 PetscFunctionReturn(0); 2461 } 2462 2463 /*@ 2464 DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2465 2466 Not collective 2467 2468 Input Parameters: 2469 + mesh - The DMPlex 2470 . p - The point, which must lie in the chart set with DMPlexSetChart() 2471 - size - The cone size for point p 2472 2473 Output Parameter: 2474 2475 Note: 2476 This should be called after DMPlexSetChart(). 2477 2478 Level: beginner 2479 2480 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 2481 @*/ 2482 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2483 { 2484 DM_Plex *mesh = (DM_Plex*) dm->data; 2485 PetscErrorCode ierr; 2486 2487 PetscFunctionBegin; 2488 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2489 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2490 2491 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 2492 PetscFunctionReturn(0); 2493 } 2494 2495 /*@ 2496 DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2497 2498 Not collective 2499 2500 Input Parameters: 2501 + mesh - The DMPlex 2502 . p - The point, which must lie in the chart set with DMPlexSetChart() 2503 - size - The additional cone size for point p 2504 2505 Output Parameter: 2506 2507 Note: 2508 This should be called after DMPlexSetChart(). 2509 2510 Level: beginner 2511 2512 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 2513 @*/ 2514 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2515 { 2516 DM_Plex *mesh = (DM_Plex*) dm->data; 2517 PetscInt csize; 2518 PetscErrorCode ierr; 2519 2520 PetscFunctionBegin; 2521 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2522 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2523 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 2524 2525 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 2526 PetscFunctionReturn(0); 2527 } 2528 2529 /*@C 2530 DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2531 2532 Not collective 2533 2534 Input Parameters: 2535 + dm - The DMPlex 2536 - p - The point, which must lie in the chart set with DMPlexSetChart() 2537 2538 Output Parameter: 2539 . cone - An array of points which are on the in-edges for point p 2540 2541 Level: beginner 2542 2543 Fortran Notes: 2544 Since it returns an array, this routine is only available in Fortran 90, and you must 2545 include petsc.h90 in your code. 2546 You must also call DMPlexRestoreCone() after you finish using the returned array. 2547 DMPlexRestoreCone() is not needed/available in C. 2548 2549 .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart() 2550 @*/ 2551 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2552 { 2553 DM_Plex *mesh = (DM_Plex*) dm->data; 2554 PetscInt off; 2555 PetscErrorCode ierr; 2556 2557 PetscFunctionBegin; 2558 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2559 PetscValidPointer(cone, 3); 2560 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2561 *cone = &mesh->cones[off]; 2562 PetscFunctionReturn(0); 2563 } 2564 2565 /*@C 2566 DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 2567 2568 Not collective 2569 2570 Input Parameters: 2571 + dm - The DMPlex 2572 - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 2573 2574 Output Parameters: 2575 + pConesSection - PetscSection describing the layout of pCones 2576 - pCones - An array of points which are on the in-edges for the point set p 2577 2578 Level: intermediate 2579 2580 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart() 2581 @*/ 2582 PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 2583 { 2584 PetscSection cs, newcs; 2585 PetscInt *cones; 2586 PetscInt *newarr=NULL; 2587 PetscInt n; 2588 PetscErrorCode ierr; 2589 2590 PetscFunctionBegin; 2591 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 2592 ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr); 2593 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 2594 if (pConesSection) *pConesSection = newcs; 2595 if (pCones) { 2596 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 2597 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr); 2598 } 2599 PetscFunctionReturn(0); 2600 } 2601 2602 /*@ 2603 DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2604 2605 Not collective 2606 2607 Input Parameters: 2608 + dm - The DMPlex 2609 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2610 2611 Output Parameter: 2612 . expandedPoints - An array of vertices recursively expanded from input points 2613 2614 Level: advanced 2615 2616 Notes: 2617 Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2618 There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2619 2620 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth() 2621 @*/ 2622 PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2623 { 2624 IS *expandedPointsAll; 2625 PetscInt depth; 2626 PetscErrorCode ierr; 2627 2628 PetscFunctionBegin; 2629 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2630 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2631 PetscValidPointer(expandedPoints, 3); 2632 ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2633 *expandedPoints = expandedPointsAll[0]; 2634 ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]);CHKERRQ(ierr); 2635 ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2636 PetscFunctionReturn(0); 2637 } 2638 2639 /*@ 2640 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). 2641 2642 Not collective 2643 2644 Input Parameters: 2645 + dm - The DMPlex 2646 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2647 2648 Output Parameters: 2649 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2650 . expandedPoints - (optional) An array of index sets with recursively expanded cones 2651 - sections - (optional) An array of sections which describe mappings from points to their cone points 2652 2653 Level: advanced 2654 2655 Notes: 2656 Like DMPlexGetConeTuple() but recursive. 2657 2658 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. 2659 For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2660 2661 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: 2662 (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2663 (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2664 2665 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2666 @*/ 2667 PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2668 { 2669 const PetscInt *arr0=NULL, *cone=NULL; 2670 PetscInt *arr=NULL, *newarr=NULL; 2671 PetscInt d, depth_, i, n, newn, cn, co, start, end; 2672 IS *expandedPoints_; 2673 PetscSection *sections_; 2674 PetscErrorCode ierr; 2675 2676 PetscFunctionBegin; 2677 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2678 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2679 if (depth) PetscValidIntPointer(depth, 3); 2680 if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2681 if (sections) PetscValidPointer(sections, 5); 2682 ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr); 2683 ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr); 2684 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2685 ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr); 2686 ierr = PetscCalloc1(depth_, §ions_);CHKERRQ(ierr); 2687 arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2688 for (d=depth_-1; d>=0; d--) { 2689 ierr = PetscSectionCreate(PETSC_COMM_SELF, §ions_[d]);CHKERRQ(ierr); 2690 ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr); 2691 for (i=0; i<n; i++) { 2692 ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr); 2693 if (arr[i] >= start && arr[i] < end) { 2694 ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr); 2695 ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr); 2696 } else { 2697 ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr); 2698 } 2699 } 2700 ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr); 2701 ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr); 2702 ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr); 2703 for (i=0; i<n; i++) { 2704 ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr); 2705 ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr); 2706 if (cn > 1) { 2707 ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr); 2708 ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr); 2709 } else { 2710 newarr[co] = arr[i]; 2711 } 2712 } 2713 ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr); 2714 arr = newarr; 2715 n = newn; 2716 } 2717 ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr); 2718 *depth = depth_; 2719 if (expandedPoints) *expandedPoints = expandedPoints_; 2720 else { 2721 for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);} 2722 ierr = PetscFree(expandedPoints_);CHKERRQ(ierr); 2723 } 2724 if (sections) *sections = sections_; 2725 else { 2726 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(§ions_[d]);CHKERRQ(ierr);} 2727 ierr = PetscFree(sections_);CHKERRQ(ierr); 2728 } 2729 PetscFunctionReturn(0); 2730 } 2731 2732 /*@ 2733 DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2734 2735 Not collective 2736 2737 Input Parameters: 2738 + dm - The DMPlex 2739 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2740 2741 Output Parameters: 2742 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2743 . expandedPoints - (optional) An array of recursively expanded cones 2744 - sections - (optional) An array of sections which describe mappings from points to their cone points 2745 2746 Level: advanced 2747 2748 Notes: 2749 See DMPlexGetConeRecursive() for details. 2750 2751 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2752 @*/ 2753 PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2754 { 2755 PetscInt d, depth_; 2756 PetscErrorCode ierr; 2757 2758 PetscFunctionBegin; 2759 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2760 if (depth && *depth != depth_) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2761 if (depth) *depth = 0; 2762 if (expandedPoints) { 2763 for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);} 2764 ierr = PetscFree(*expandedPoints);CHKERRQ(ierr); 2765 } 2766 if (sections) { 2767 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);} 2768 ierr = PetscFree(*sections);CHKERRQ(ierr); 2769 } 2770 PetscFunctionReturn(0); 2771 } 2772 2773 /*@ 2774 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 2775 2776 Not collective 2777 2778 Input Parameters: 2779 + mesh - The DMPlex 2780 . p - The point, which must lie in the chart set with DMPlexSetChart() 2781 - cone - An array of points which are on the in-edges for point p 2782 2783 Output Parameter: 2784 2785 Note: 2786 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2787 2788 Level: beginner 2789 2790 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize() 2791 @*/ 2792 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 2793 { 2794 DM_Plex *mesh = (DM_Plex*) dm->data; 2795 PetscInt pStart, pEnd; 2796 PetscInt dof, off, c; 2797 PetscErrorCode ierr; 2798 2799 PetscFunctionBegin; 2800 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2801 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2802 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2803 if (dof) PetscValidPointer(cone, 3); 2804 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2805 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); 2806 for (c = 0; c < dof; ++c) { 2807 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); 2808 mesh->cones[off+c] = cone[c]; 2809 } 2810 PetscFunctionReturn(0); 2811 } 2812 2813 /*@C 2814 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 2815 2816 Not collective 2817 2818 Input Parameters: 2819 + mesh - The DMPlex 2820 - p - The point, which must lie in the chart set with DMPlexSetChart() 2821 2822 Output Parameter: 2823 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2824 integer giving the prescription for cone traversal. 2825 2826 Level: beginner 2827 2828 Notes: 2829 The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 2830 the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 2831 of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 2832 with the identity. 2833 2834 Fortran Notes: 2835 Since it returns an array, this routine is only available in Fortran 90, and you must 2836 include petsc.h90 in your code. 2837 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 2838 DMPlexRestoreConeOrientation() is not needed/available in C. 2839 2840 .seealso: DMPolytopeTypeComposeOrientation(), DMPolytopeTypeComposeOrientationInv(), DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 2841 @*/ 2842 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 2843 { 2844 DM_Plex *mesh = (DM_Plex*) dm->data; 2845 PetscInt off; 2846 PetscErrorCode ierr; 2847 2848 PetscFunctionBegin; 2849 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2850 if (PetscDefined(USE_DEBUG)) { 2851 PetscInt dof; 2852 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2853 if (dof) PetscValidPointer(coneOrientation, 3); 2854 } 2855 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2856 2857 *coneOrientation = &mesh->coneOrientations[off]; 2858 PetscFunctionReturn(0); 2859 } 2860 2861 /*@ 2862 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 2863 2864 Not collective 2865 2866 Input Parameters: 2867 + mesh - The DMPlex 2868 . p - The point, which must lie in the chart set with DMPlexSetChart() 2869 - coneOrientation - An array of orientations 2870 Output Parameter: 2871 2872 Notes: 2873 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2874 2875 The meaning of coneOrientation is detailed in DMPlexGetConeOrientation(). 2876 2877 Level: beginner 2878 2879 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2880 @*/ 2881 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 2882 { 2883 DM_Plex *mesh = (DM_Plex*) dm->data; 2884 PetscInt pStart, pEnd; 2885 PetscInt dof, off, c; 2886 PetscErrorCode ierr; 2887 2888 PetscFunctionBegin; 2889 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2890 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2891 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2892 if (dof) PetscValidPointer(coneOrientation, 3); 2893 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2894 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); 2895 for (c = 0; c < dof; ++c) { 2896 PetscInt cdof, o = coneOrientation[c]; 2897 2898 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 2899 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); 2900 mesh->coneOrientations[off+c] = o; 2901 } 2902 PetscFunctionReturn(0); 2903 } 2904 2905 /*@ 2906 DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 2907 2908 Not collective 2909 2910 Input Parameters: 2911 + mesh - The DMPlex 2912 . p - The point, which must lie in the chart set with DMPlexSetChart() 2913 . conePos - The local index in the cone where the point should be put 2914 - conePoint - The mesh point to insert 2915 2916 Level: beginner 2917 2918 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2919 @*/ 2920 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 2921 { 2922 DM_Plex *mesh = (DM_Plex*) dm->data; 2923 PetscInt pStart, pEnd; 2924 PetscInt dof, off; 2925 PetscErrorCode ierr; 2926 2927 PetscFunctionBegin; 2928 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2929 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2930 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); 2931 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); 2932 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2933 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2934 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); 2935 mesh->cones[off+conePos] = conePoint; 2936 PetscFunctionReturn(0); 2937 } 2938 2939 /*@ 2940 DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 2941 2942 Not collective 2943 2944 Input Parameters: 2945 + mesh - The DMPlex 2946 . p - The point, which must lie in the chart set with DMPlexSetChart() 2947 . conePos - The local index in the cone where the point should be put 2948 - coneOrientation - The point orientation to insert 2949 2950 Level: beginner 2951 2952 Notes: 2953 The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation(). 2954 2955 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2956 @*/ 2957 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 2958 { 2959 DM_Plex *mesh = (DM_Plex*) dm->data; 2960 PetscInt pStart, pEnd; 2961 PetscInt dof, off; 2962 PetscErrorCode ierr; 2963 2964 PetscFunctionBegin; 2965 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2966 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2967 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); 2968 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2969 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2970 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); 2971 mesh->coneOrientations[off+conePos] = coneOrientation; 2972 PetscFunctionReturn(0); 2973 } 2974 2975 /*@ 2976 DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 2977 2978 Not collective 2979 2980 Input Parameters: 2981 + mesh - The DMPlex 2982 - p - The point, which must lie in the chart set with DMPlexSetChart() 2983 2984 Output Parameter: 2985 . size - The support size for point p 2986 2987 Level: beginner 2988 2989 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 2990 @*/ 2991 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 2992 { 2993 DM_Plex *mesh = (DM_Plex*) dm->data; 2994 PetscErrorCode ierr; 2995 2996 PetscFunctionBegin; 2997 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2998 PetscValidPointer(size, 3); 2999 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3000 PetscFunctionReturn(0); 3001 } 3002 3003 /*@ 3004 DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3005 3006 Not collective 3007 3008 Input Parameters: 3009 + mesh - The DMPlex 3010 . p - The point, which must lie in the chart set with DMPlexSetChart() 3011 - size - The support size for point p 3012 3013 Output Parameter: 3014 3015 Note: 3016 This should be called after DMPlexSetChart(). 3017 3018 Level: beginner 3019 3020 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 3021 @*/ 3022 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3023 { 3024 DM_Plex *mesh = (DM_Plex*) dm->data; 3025 PetscErrorCode ierr; 3026 3027 PetscFunctionBegin; 3028 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3029 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3030 3031 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 3032 PetscFunctionReturn(0); 3033 } 3034 3035 /*@C 3036 DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3037 3038 Not collective 3039 3040 Input Parameters: 3041 + mesh - The DMPlex 3042 - p - The point, which must lie in the chart set with DMPlexSetChart() 3043 3044 Output Parameter: 3045 . support - An array of points which are on the out-edges for point p 3046 3047 Level: beginner 3048 3049 Fortran Notes: 3050 Since it returns an array, this routine is only available in Fortran 90, and you must 3051 include petsc.h90 in your code. 3052 You must also call DMPlexRestoreSupport() after you finish using the returned array. 3053 DMPlexRestoreSupport() is not needed/available in C. 3054 3055 .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart() 3056 @*/ 3057 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3058 { 3059 DM_Plex *mesh = (DM_Plex*) dm->data; 3060 PetscInt off; 3061 PetscErrorCode ierr; 3062 3063 PetscFunctionBegin; 3064 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3065 PetscValidPointer(support, 3); 3066 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3067 *support = &mesh->supports[off]; 3068 PetscFunctionReturn(0); 3069 } 3070 3071 /*@ 3072 DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 3073 3074 Not collective 3075 3076 Input Parameters: 3077 + mesh - The DMPlex 3078 . p - The point, which must lie in the chart set with DMPlexSetChart() 3079 - support - An array of points which are on the out-edges for point p 3080 3081 Output Parameter: 3082 3083 Note: 3084 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 3085 3086 Level: beginner 3087 3088 .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 3089 @*/ 3090 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3091 { 3092 DM_Plex *mesh = (DM_Plex*) dm->data; 3093 PetscInt pStart, pEnd; 3094 PetscInt dof, off, c; 3095 PetscErrorCode ierr; 3096 3097 PetscFunctionBegin; 3098 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3099 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3100 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3101 if (dof) PetscValidPointer(support, 3); 3102 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3103 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); 3104 for (c = 0; c < dof; ++c) { 3105 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); 3106 mesh->supports[off+c] = support[c]; 3107 } 3108 PetscFunctionReturn(0); 3109 } 3110 3111 /*@ 3112 DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 3113 3114 Not collective 3115 3116 Input Parameters: 3117 + mesh - The DMPlex 3118 . p - The point, which must lie in the chart set with DMPlexSetChart() 3119 . supportPos - The local index in the cone where the point should be put 3120 - supportPoint - The mesh point to insert 3121 3122 Level: beginner 3123 3124 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3125 @*/ 3126 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3127 { 3128 DM_Plex *mesh = (DM_Plex*) dm->data; 3129 PetscInt pStart, pEnd; 3130 PetscInt dof, off; 3131 PetscErrorCode ierr; 3132 3133 PetscFunctionBegin; 3134 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3135 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3136 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3137 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3138 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); 3139 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); 3140 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); 3141 mesh->supports[off+supportPos] = supportPoint; 3142 PetscFunctionReturn(0); 3143 } 3144 3145 /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3146 PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3147 { 3148 switch (ct) { 3149 case DM_POLYTOPE_SEGMENT: 3150 if (o == -1) return -2; 3151 break; 3152 case DM_POLYTOPE_TRIANGLE: 3153 if (o == -3) return -1; 3154 if (o == -2) return -3; 3155 if (o == -1) return -2; 3156 break; 3157 case DM_POLYTOPE_QUADRILATERAL: 3158 if (o == -4) return -2; 3159 if (o == -3) return -1; 3160 if (o == -2) return -4; 3161 if (o == -1) return -3; 3162 break; 3163 default: return o; 3164 } 3165 return o; 3166 } 3167 3168 /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3169 PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3170 { 3171 switch (ct) { 3172 case DM_POLYTOPE_SEGMENT: 3173 if ((o == -2) || (o == 1)) return -1; 3174 if (o == -1) return 0; 3175 break; 3176 case DM_POLYTOPE_TRIANGLE: 3177 if (o == -3) return -2; 3178 if (o == -2) return -1; 3179 if (o == -1) return -3; 3180 break; 3181 case DM_POLYTOPE_QUADRILATERAL: 3182 if (o == -4) return -2; 3183 if (o == -3) return -1; 3184 if (o == -2) return -4; 3185 if (o == -1) return -3; 3186 break; 3187 default: return o; 3188 } 3189 return o; 3190 } 3191 3192 /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3193 PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3194 { 3195 PetscInt pStart, pEnd, p; 3196 PetscErrorCode ierr; 3197 3198 PetscFunctionBegin; 3199 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3200 for (p = pStart; p < pEnd; ++p) { 3201 const PetscInt *cone, *ornt; 3202 PetscInt coneSize, c; 3203 3204 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3205 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 3206 ierr = DMPlexGetConeOrientation(dm, p, &ornt);CHKERRQ(ierr); 3207 for (c = 0; c < coneSize; ++c) { 3208 DMPolytopeType ct; 3209 const PetscInt o = ornt[c]; 3210 3211 ierr = DMPlexGetCellType(dm, cone[c], &ct);CHKERRQ(ierr); 3212 switch (ct) { 3213 case DM_POLYTOPE_SEGMENT: 3214 if ((o == -2) || (o == 1)) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3215 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, 0);CHKERRQ(ierr);} 3216 break; 3217 case DM_POLYTOPE_TRIANGLE: 3218 if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);} 3219 if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3220 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);} 3221 break; 3222 case DM_POLYTOPE_QUADRILATERAL: 3223 if (o == -4) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);} 3224 if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3225 if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -4);CHKERRQ(ierr);} 3226 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);} 3227 break; 3228 default: break; 3229 } 3230 } 3231 } 3232 PetscFunctionReturn(0); 3233 } 3234 3235 static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3236 { 3237 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3238 PetscInt *closure; 3239 const PetscInt *tmp = NULL, *tmpO = NULL; 3240 PetscInt off = 0, tmpSize, t; 3241 PetscErrorCode ierr; 3242 3243 PetscFunctionBeginHot; 3244 if (ornt) { 3245 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3246 if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3247 } 3248 if (*points) { 3249 closure = *points; 3250 } else { 3251 PetscInt maxConeSize, maxSupportSize; 3252 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3253 ierr = DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure);CHKERRQ(ierr); 3254 } 3255 if (useCone) { 3256 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 3257 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 3258 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 3259 } else { 3260 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 3261 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 3262 } 3263 if (ct == DM_POLYTOPE_UNKNOWN) { 3264 closure[off++] = p; 3265 closure[off++] = 0; 3266 for (t = 0; t < tmpSize; ++t) { 3267 closure[off++] = tmp[t]; 3268 closure[off++] = tmpO ? tmpO[t] : 0; 3269 } 3270 } else { 3271 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);CHKERRQ(ierr); 3272 3273 /* We assume that cells with a valid type have faces with a valid type */ 3274 closure[off++] = p; 3275 closure[off++] = ornt; 3276 for (t = 0; t < tmpSize; ++t) { 3277 DMPolytopeType ft; 3278 3279 ierr = DMPlexGetCellType(dm, tmp[t], &ft);CHKERRQ(ierr); 3280 closure[off++] = tmp[arr[t]]; 3281 closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3282 } 3283 } 3284 if (numPoints) *numPoints = tmpSize+1; 3285 if (points) *points = closure; 3286 PetscFunctionReturn(0); 3287 } 3288 3289 /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */ 3290 static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3291 { 3292 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3293 const PetscInt *cone, *ornt; 3294 PetscInt *pts, *closure = NULL; 3295 DMPolytopeType ft; 3296 PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3297 PetscInt dim, coneSize, c, d, clSize, cl; 3298 PetscErrorCode ierr; 3299 3300 PetscFunctionBeginHot; 3301 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3302 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 3303 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3304 ierr = DMPlexGetConeOrientation(dm, point, &ornt);CHKERRQ(ierr); 3305 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3306 coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim+1)-1)/(maxConeSize-1)) : dim+1; 3307 supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1; 3308 maxSize = PetscMax(coneSeries, supportSeries); 3309 if (*points) {pts = *points;} 3310 else {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts);CHKERRQ(ierr);} 3311 c = 0; 3312 pts[c++] = point; 3313 pts[c++] = o; 3314 ierr = DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft);CHKERRQ(ierr); 3315 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), 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 = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure);CHKERRQ(ierr); 3318 for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 3319 ierr = DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure);CHKERRQ(ierr); 3320 for (d = 2; d < coneSize; ++d) { 3321 ierr = DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft);CHKERRQ(ierr); 3322 pts[c++] = cone[arr[d*2+0]]; 3323 pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]); 3324 } 3325 if (dim >= 3) { 3326 for (d = 2; d < coneSize; ++d) { 3327 const PetscInt fpoint = cone[arr[d*2+0]]; 3328 const PetscInt *fcone, *fornt; 3329 PetscInt fconeSize, fc, i; 3330 3331 ierr = DMPlexGetCellType(dm, fpoint, &ft);CHKERRQ(ierr); 3332 const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d])); 3333 ierr = DMPlexGetConeSize(dm, fpoint, &fconeSize);CHKERRQ(ierr); 3334 ierr = DMPlexGetCone(dm, fpoint, &fcone);CHKERRQ(ierr); 3335 ierr = DMPlexGetConeOrientation(dm, fpoint, &fornt);CHKERRQ(ierr); 3336 for (fc = 0; fc < fconeSize; ++fc) { 3337 const PetscInt cp = fcone[farr[fc*2+0]]; 3338 const PetscInt co = farr[fc*2+1]; 3339 3340 for (i = 0; i < c; i += 2) if (pts[i] == cp) break; 3341 if (i == c) { 3342 ierr = DMPlexGetCellType(dm, cp, &ft);CHKERRQ(ierr); 3343 pts[c++] = cp; 3344 pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]); 3345 } 3346 } 3347 } 3348 } 3349 *numPoints = c/2; 3350 *points = pts; 3351 PetscFunctionReturn(0); 3352 } 3353 3354 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3355 { 3356 DMPolytopeType ct; 3357 PetscInt *closure, *fifo; 3358 PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3359 PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3360 PetscInt depth, maxSize; 3361 PetscErrorCode ierr; 3362 3363 PetscFunctionBeginHot; 3364 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3365 if (depth == 1) { 3366 ierr = DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points);CHKERRQ(ierr); 3367 PetscFunctionReturn(0); 3368 } 3369 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3370 if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3371 if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 3372 ierr = DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points);CHKERRQ(ierr); 3373 PetscFunctionReturn(0); 3374 } 3375 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3376 coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth+1)-1)/(maxConeSize-1)) : depth+1; 3377 supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1; 3378 maxSize = PetscMax(coneSeries, supportSeries); 3379 ierr = DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3380 if (*points) {closure = *points;} 3381 else {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure);CHKERRQ(ierr);} 3382 closure[closureSize++] = p; 3383 closure[closureSize++] = ornt; 3384 fifo[fifoSize++] = p; 3385 fifo[fifoSize++] = ornt; 3386 fifo[fifoSize++] = ct; 3387 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3388 while (fifoSize - fifoStart) { 3389 const PetscInt q = fifo[fifoStart++]; 3390 const PetscInt o = fifo[fifoStart++]; 3391 const DMPolytopeType qt = (DMPolytopeType) fifo[fifoStart++]; 3392 const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 3393 const PetscInt *tmp, *tmpO; 3394 PetscInt tmpSize, t; 3395 3396 if (PetscDefined(USE_DEBUG)) { 3397 PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2; 3398 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); 3399 } 3400 if (useCone) { 3401 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 3402 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 3403 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 3404 } else { 3405 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 3406 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 3407 tmpO = NULL; 3408 } 3409 for (t = 0; t < tmpSize; ++t) { 3410 const PetscInt ip = useCone && qarr ? qarr[t*2] : t; 3411 const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0; 3412 const PetscInt cp = tmp[ip]; 3413 ierr = DMPlexGetCellType(dm, cp, &ct);CHKERRQ(ierr); 3414 const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3415 PetscInt c; 3416 3417 /* Check for duplicate */ 3418 for (c = 0; c < closureSize; c += 2) { 3419 if (closure[c] == cp) break; 3420 } 3421 if (c == closureSize) { 3422 closure[closureSize++] = cp; 3423 closure[closureSize++] = co; 3424 fifo[fifoSize++] = cp; 3425 fifo[fifoSize++] = co; 3426 fifo[fifoSize++] = ct; 3427 } 3428 } 3429 } 3430 ierr = DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3431 if (numPoints) *numPoints = closureSize/2; 3432 if (points) *points = closure; 3433 PetscFunctionReturn(0); 3434 } 3435 3436 /*@C 3437 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3438 3439 Not collective 3440 3441 Input Parameters: 3442 + dm - The DMPlex 3443 . p - The mesh point 3444 - useCone - PETSC_TRUE for the closure, otherwise return the star 3445 3446 Input/Output Parameter: 3447 . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 3448 if NULL on input, internal storage will be returned, otherwise the provided array is used 3449 3450 Output Parameter: 3451 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3452 3453 Note: 3454 If using internal storage (points is NULL on input), each call overwrites the last output. 3455 3456 Fortran Notes: 3457 Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3458 3459 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3460 3461 Level: beginner 3462 3463 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3464 @*/ 3465 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3466 { 3467 PetscErrorCode ierr; 3468 3469 PetscFunctionBeginHot; 3470 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3471 if (numPoints) PetscValidIntPointer(numPoints, 4); 3472 if (points) PetscValidPointer(points, 5); 3473 ierr = DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points);CHKERRQ(ierr); 3474 PetscFunctionReturn(0); 3475 } 3476 3477 /*@C 3478 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3479 3480 Not collective 3481 3482 Input Parameters: 3483 + dm - The DMPlex 3484 . p - The mesh point 3485 . useCone - PETSC_TRUE for the closure, otherwise return the star 3486 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3487 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3488 3489 Note: 3490 If not using internal storage (points is not NULL on input), this call is unnecessary 3491 3492 Fortran Notes: 3493 Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3494 3495 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3496 3497 Level: beginner 3498 3499 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3500 @*/ 3501 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3502 { 3503 PetscErrorCode ierr; 3504 3505 PetscFunctionBeginHot; 3506 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3507 if (numPoints) *numPoints = 0; 3508 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr); 3509 PetscFunctionReturn(0); 3510 } 3511 3512 /*@ 3513 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3514 3515 Not collective 3516 3517 Input Parameter: 3518 . mesh - The DMPlex 3519 3520 Output Parameters: 3521 + maxConeSize - The maximum number of in-edges 3522 - maxSupportSize - The maximum number of out-edges 3523 3524 Level: beginner 3525 3526 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 3527 @*/ 3528 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3529 { 3530 DM_Plex *mesh = (DM_Plex*) dm->data; 3531 3532 PetscFunctionBegin; 3533 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3534 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 3535 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 3536 PetscFunctionReturn(0); 3537 } 3538 3539 PetscErrorCode DMSetUp_Plex(DM dm) 3540 { 3541 DM_Plex *mesh = (DM_Plex*) dm->data; 3542 PetscInt size; 3543 PetscErrorCode ierr; 3544 3545 PetscFunctionBegin; 3546 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3547 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 3548 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 3549 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 3550 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 3551 ierr = PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt));CHKERRQ(ierr); 3552 if (mesh->maxSupportSize) { 3553 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3554 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 3555 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 3556 ierr = PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt));CHKERRQ(ierr); 3557 } 3558 PetscFunctionReturn(0); 3559 } 3560 3561 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3562 { 3563 PetscErrorCode ierr; 3564 3565 PetscFunctionBegin; 3566 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 3567 ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 3568 if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3569 if (dm->useNatural && dm->sfMigration) { 3570 PetscSF sfMigrationInv,sfNatural; 3571 PetscSection section, sectionSeq; 3572 3573 (*subdm)->sfMigration = dm->sfMigration; 3574 ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr); 3575 ierr = DMGetLocalSection((*subdm), §ion);CHKERRQ(ierr); 3576 ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3577 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq);CHKERRQ(ierr); 3578 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3579 3580 ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3581 (*subdm)->sfNatural = sfNatural; 3582 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3583 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3584 } 3585 PetscFunctionReturn(0); 3586 } 3587 3588 PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 3589 { 3590 PetscErrorCode ierr; 3591 PetscInt i = 0; 3592 3593 PetscFunctionBegin; 3594 ierr = DMClone(dms[0], superdm);CHKERRQ(ierr); 3595 ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr); 3596 (*superdm)->useNatural = PETSC_FALSE; 3597 for (i = 0; i < len; i++) { 3598 if (dms[i]->useNatural && dms[i]->sfMigration) { 3599 PetscSF sfMigrationInv,sfNatural; 3600 PetscSection section, sectionSeq; 3601 3602 (*superdm)->sfMigration = dms[i]->sfMigration; 3603 ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr); 3604 (*superdm)->useNatural = PETSC_TRUE; 3605 ierr = DMGetLocalSection((*superdm), §ion);CHKERRQ(ierr); 3606 ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3607 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq);CHKERRQ(ierr); 3608 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3609 3610 ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3611 (*superdm)->sfNatural = sfNatural; 3612 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3613 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3614 break; 3615 } 3616 } 3617 PetscFunctionReturn(0); 3618 } 3619 3620 /*@ 3621 DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3622 3623 Not collective 3624 3625 Input Parameter: 3626 . mesh - The DMPlex 3627 3628 Output Parameter: 3629 3630 Note: 3631 This should be called after all calls to DMPlexSetCone() 3632 3633 Level: beginner 3634 3635 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 3636 @*/ 3637 PetscErrorCode DMPlexSymmetrize(DM dm) 3638 { 3639 DM_Plex *mesh = (DM_Plex*) dm->data; 3640 PetscInt *offsets; 3641 PetscInt supportSize; 3642 PetscInt pStart, pEnd, p; 3643 PetscErrorCode ierr; 3644 3645 PetscFunctionBegin; 3646 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3647 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 3648 ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3649 /* Calculate support sizes */ 3650 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3651 for (p = pStart; p < pEnd; ++p) { 3652 PetscInt dof, off, c; 3653 3654 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3655 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3656 for (c = off; c < off+dof; ++c) { 3657 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 3658 } 3659 } 3660 for (p = pStart; p < pEnd; ++p) { 3661 PetscInt dof; 3662 3663 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3664 3665 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 3666 } 3667 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3668 /* Calculate supports */ 3669 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 3670 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 3671 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 3672 for (p = pStart; p < pEnd; ++p) { 3673 PetscInt dof, off, c; 3674 3675 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3676 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3677 for (c = off; c < off+dof; ++c) { 3678 const PetscInt q = mesh->cones[c]; 3679 PetscInt offS; 3680 3681 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 3682 3683 mesh->supports[offS+offsets[q]] = p; 3684 ++offsets[q]; 3685 } 3686 } 3687 ierr = PetscFree(offsets);CHKERRQ(ierr); 3688 ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3689 PetscFunctionReturn(0); 3690 } 3691 3692 static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3693 { 3694 IS stratumIS; 3695 PetscErrorCode ierr; 3696 3697 PetscFunctionBegin; 3698 if (pStart >= pEnd) PetscFunctionReturn(0); 3699 if (PetscDefined(USE_DEBUG)) { 3700 PetscInt qStart, qEnd, numLevels, level; 3701 PetscBool overlap = PETSC_FALSE; 3702 ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr); 3703 for (level = 0; level < numLevels; level++) { 3704 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3705 if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3706 } 3707 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); 3708 } 3709 ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr); 3710 ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr); 3711 ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 3712 PetscFunctionReturn(0); 3713 } 3714 3715 /*@ 3716 DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 3717 can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3718 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3719 the DAG. 3720 3721 Collective on dm 3722 3723 Input Parameter: 3724 . mesh - The DMPlex 3725 3726 Output Parameter: 3727 3728 Notes: 3729 Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3730 meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 3731 until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3732 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3733 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3734 3735 The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3736 if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3737 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 3738 to interpolate only that one (e0), so that 3739 $ cone(c0) = {e0, v2} 3740 $ cone(e0) = {v0, v1} 3741 If DMPlexStratify() is run on this mesh, it will give depths 3742 $ depth 0 = {v0, v1, v2} 3743 $ depth 1 = {e0, c0} 3744 where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3745 3746 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3747 3748 Level: beginner 3749 3750 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes() 3751 @*/ 3752 PetscErrorCode DMPlexStratify(DM dm) 3753 { 3754 DM_Plex *mesh = (DM_Plex*) dm->data; 3755 DMLabel label; 3756 PetscInt pStart, pEnd, p; 3757 PetscInt numRoots = 0, numLeaves = 0; 3758 PetscErrorCode ierr; 3759 3760 PetscFunctionBegin; 3761 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3762 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3763 3764 /* Create depth label */ 3765 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3766 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 3767 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3768 3769 { 3770 /* Initialize roots and count leaves */ 3771 PetscInt sMin = PETSC_MAX_INT; 3772 PetscInt sMax = PETSC_MIN_INT; 3773 PetscInt coneSize, supportSize; 3774 3775 for (p = pStart; p < pEnd; ++p) { 3776 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3777 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3778 if (!coneSize && supportSize) { 3779 sMin = PetscMin(p, sMin); 3780 sMax = PetscMax(p, sMax); 3781 ++numRoots; 3782 } else if (!supportSize && coneSize) { 3783 ++numLeaves; 3784 } else if (!supportSize && !coneSize) { 3785 /* Isolated points */ 3786 sMin = PetscMin(p, sMin); 3787 sMax = PetscMax(p, sMax); 3788 } 3789 } 3790 ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr); 3791 } 3792 3793 if (numRoots + numLeaves == (pEnd - pStart)) { 3794 PetscInt sMin = PETSC_MAX_INT; 3795 PetscInt sMax = PETSC_MIN_INT; 3796 PetscInt coneSize, supportSize; 3797 3798 for (p = pStart; p < pEnd; ++p) { 3799 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3800 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3801 if (!supportSize && coneSize) { 3802 sMin = PetscMin(p, sMin); 3803 sMax = PetscMax(p, sMax); 3804 } 3805 } 3806 ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr); 3807 } else { 3808 PetscInt level = 0; 3809 PetscInt qStart, qEnd, q; 3810 3811 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3812 while (qEnd > qStart) { 3813 PetscInt sMin = PETSC_MAX_INT; 3814 PetscInt sMax = PETSC_MIN_INT; 3815 3816 for (q = qStart; q < qEnd; ++q) { 3817 const PetscInt *support; 3818 PetscInt supportSize, s; 3819 3820 ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr); 3821 ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr); 3822 for (s = 0; s < supportSize; ++s) { 3823 sMin = PetscMin(support[s], sMin); 3824 sMax = PetscMax(support[s], sMax); 3825 } 3826 } 3827 ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr); 3828 ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr); 3829 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3830 } 3831 } 3832 { /* just in case there is an empty process */ 3833 PetscInt numValues, maxValues = 0, v; 3834 3835 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 3836 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 3837 for (v = numValues; v < maxValues; v++) { 3838 ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr); 3839 } 3840 } 3841 ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr); 3842 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3843 PetscFunctionReturn(0); 3844 } 3845 3846 PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 3847 { 3848 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3849 PetscInt dim, depth, pheight, coneSize; 3850 PetscErrorCode ierr; 3851 3852 PetscFunctionBeginHot; 3853 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3854 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3855 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3856 pheight = depth - pdepth; 3857 if (depth <= 1) { 3858 switch (pdepth) { 3859 case 0: ct = DM_POLYTOPE_POINT;break; 3860 case 1: 3861 switch (coneSize) { 3862 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3863 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3864 case 4: 3865 switch (dim) { 3866 case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 3867 case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 3868 default: break; 3869 } 3870 break; 3871 case 5: ct = DM_POLYTOPE_PYRAMID;break; 3872 case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3873 case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 3874 default: break; 3875 } 3876 } 3877 } else { 3878 if (pdepth == 0) { 3879 ct = DM_POLYTOPE_POINT; 3880 } else if (pheight == 0) { 3881 switch (dim) { 3882 case 1: 3883 switch (coneSize) { 3884 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3885 default: break; 3886 } 3887 break; 3888 case 2: 3889 switch (coneSize) { 3890 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3891 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3892 default: break; 3893 } 3894 break; 3895 case 3: 3896 switch (coneSize) { 3897 case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 3898 case 5: 3899 { 3900 const PetscInt *cone; 3901 PetscInt faceConeSize; 3902 3903 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 3904 ierr = DMPlexGetConeSize(dm, cone[0], &faceConeSize);CHKERRQ(ierr); 3905 switch (faceConeSize) { 3906 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3907 case 4: ct = DM_POLYTOPE_PYRAMID;break; 3908 } 3909 } 3910 break; 3911 case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 3912 default: break; 3913 } 3914 break; 3915 default: break; 3916 } 3917 } else if (pheight > 0) { 3918 switch (coneSize) { 3919 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3920 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3921 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3922 default: break; 3923 } 3924 } 3925 } 3926 *pt = ct; 3927 PetscFunctionReturn(0); 3928 } 3929 3930 /*@ 3931 DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 3932 3933 Collective on dm 3934 3935 Input Parameter: 3936 . mesh - The DMPlex 3937 3938 DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 3939 3940 Level: developer 3941 3942 Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 3943 internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 3944 automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 3945 3946 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel() 3947 @*/ 3948 PetscErrorCode DMPlexComputeCellTypes(DM dm) 3949 { 3950 DM_Plex *mesh; 3951 DMLabel ctLabel; 3952 PetscInt pStart, pEnd, p; 3953 PetscErrorCode ierr; 3954 3955 PetscFunctionBegin; 3956 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3957 mesh = (DM_Plex *) dm->data; 3958 ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr); 3959 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 3960 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3961 for (p = pStart; p < pEnd; ++p) { 3962 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3963 PetscInt pdepth; 3964 3965 ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr); 3966 ierr = DMPlexComputeCellType_Internal(dm, p, pdepth, &ct);CHKERRQ(ierr); 3967 if (ct == DM_POLYTOPE_UNKNOWN) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p); 3968 ierr = DMLabelSetValue(ctLabel, p, ct);CHKERRQ(ierr); 3969 } 3970 ierr = PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState);CHKERRQ(ierr); 3971 ierr = PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr); 3972 PetscFunctionReturn(0); 3973 } 3974 3975 /*@C 3976 DMPlexGetJoin - Get an array for the join of the set of points 3977 3978 Not Collective 3979 3980 Input Parameters: 3981 + dm - The DMPlex object 3982 . numPoints - The number of input points for the join 3983 - points - The input points 3984 3985 Output Parameters: 3986 + numCoveredPoints - The number of points in the join 3987 - coveredPoints - The points in the join 3988 3989 Level: intermediate 3990 3991 Note: Currently, this is restricted to a single level join 3992 3993 Fortran Notes: 3994 Since it returns an array, this routine is only available in Fortran 90, and you must 3995 include petsc.h90 in your code. 3996 3997 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3998 3999 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 4000 @*/ 4001 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4002 { 4003 DM_Plex *mesh = (DM_Plex*) dm->data; 4004 PetscInt *join[2]; 4005 PetscInt joinSize, i = 0; 4006 PetscInt dof, off, p, c, m; 4007 PetscErrorCode ierr; 4008 4009 PetscFunctionBegin; 4010 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4011 PetscValidIntPointer(points, 3); 4012 PetscValidIntPointer(numCoveredPoints, 4); 4013 PetscValidPointer(coveredPoints, 5); 4014 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4015 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4016 /* Copy in support of first point */ 4017 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 4018 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 4019 for (joinSize = 0; joinSize < dof; ++joinSize) { 4020 join[i][joinSize] = mesh->supports[off+joinSize]; 4021 } 4022 /* Check each successive support */ 4023 for (p = 1; p < numPoints; ++p) { 4024 PetscInt newJoinSize = 0; 4025 4026 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 4027 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 4028 for (c = 0; c < dof; ++c) { 4029 const PetscInt point = mesh->supports[off+c]; 4030 4031 for (m = 0; m < joinSize; ++m) { 4032 if (point == join[i][m]) { 4033 join[1-i][newJoinSize++] = point; 4034 break; 4035 } 4036 } 4037 } 4038 joinSize = newJoinSize; 4039 i = 1-i; 4040 } 4041 *numCoveredPoints = joinSize; 4042 *coveredPoints = join[i]; 4043 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4044 PetscFunctionReturn(0); 4045 } 4046 4047 /*@C 4048 DMPlexRestoreJoin - Restore an array for the join of the set of points 4049 4050 Not Collective 4051 4052 Input Parameters: 4053 + dm - The DMPlex object 4054 . numPoints - The number of input points for the join 4055 - points - The input points 4056 4057 Output Parameters: 4058 + numCoveredPoints - The number of points in the join 4059 - coveredPoints - The points in the join 4060 4061 Fortran Notes: 4062 Since it returns an array, this routine is only available in Fortran 90, and you must 4063 include petsc.h90 in your code. 4064 4065 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4066 4067 Level: intermediate 4068 4069 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 4070 @*/ 4071 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4072 { 4073 PetscErrorCode ierr; 4074 4075 PetscFunctionBegin; 4076 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4077 if (points) PetscValidIntPointer(points,3); 4078 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4079 PetscValidPointer(coveredPoints, 5); 4080 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4081 if (numCoveredPoints) *numCoveredPoints = 0; 4082 PetscFunctionReturn(0); 4083 } 4084 4085 /*@C 4086 DMPlexGetFullJoin - Get an array for the join of the set of points 4087 4088 Not Collective 4089 4090 Input Parameters: 4091 + dm - The DMPlex object 4092 . numPoints - The number of input points for the join 4093 - points - The input points 4094 4095 Output Parameters: 4096 + numCoveredPoints - The number of points in the join 4097 - coveredPoints - The points in the join 4098 4099 Fortran Notes: 4100 Since it returns an array, this routine is only available in Fortran 90, and you must 4101 include petsc.h90 in your code. 4102 4103 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4104 4105 Level: intermediate 4106 4107 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 4108 @*/ 4109 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4110 { 4111 DM_Plex *mesh = (DM_Plex*) dm->data; 4112 PetscInt *offsets, **closures; 4113 PetscInt *join[2]; 4114 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 4115 PetscInt p, d, c, m, ms; 4116 PetscErrorCode ierr; 4117 4118 PetscFunctionBegin; 4119 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4120 PetscValidIntPointer(points, 3); 4121 PetscValidIntPointer(numCoveredPoints, 4); 4122 PetscValidPointer(coveredPoints, 5); 4123 4124 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4125 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 4126 ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4127 ms = mesh->maxSupportSize; 4128 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 4129 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4130 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4131 4132 for (p = 0; p < numPoints; ++p) { 4133 PetscInt closureSize; 4134 4135 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 4136 4137 offsets[p*(depth+2)+0] = 0; 4138 for (d = 0; d < depth+1; ++d) { 4139 PetscInt pStart, pEnd, i; 4140 4141 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 4142 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4143 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4144 offsets[p*(depth+2)+d+1] = i; 4145 break; 4146 } 4147 } 4148 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4149 } 4150 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); 4151 } 4152 for (d = 0; d < depth+1; ++d) { 4153 PetscInt dof; 4154 4155 /* Copy in support of first point */ 4156 dof = offsets[d+1] - offsets[d]; 4157 for (joinSize = 0; joinSize < dof; ++joinSize) { 4158 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4159 } 4160 /* Check each successive cone */ 4161 for (p = 1; p < numPoints && joinSize; ++p) { 4162 PetscInt newJoinSize = 0; 4163 4164 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4165 for (c = 0; c < dof; ++c) { 4166 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4167 4168 for (m = 0; m < joinSize; ++m) { 4169 if (point == join[i][m]) { 4170 join[1-i][newJoinSize++] = point; 4171 break; 4172 } 4173 } 4174 } 4175 joinSize = newJoinSize; 4176 i = 1-i; 4177 } 4178 if (joinSize) break; 4179 } 4180 *numCoveredPoints = joinSize; 4181 *coveredPoints = join[i]; 4182 for (p = 0; p < numPoints; ++p) { 4183 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 4184 } 4185 ierr = PetscFree(closures);CHKERRQ(ierr); 4186 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4187 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4188 PetscFunctionReturn(0); 4189 } 4190 4191 /*@C 4192 DMPlexGetMeet - Get an array for the meet of the set of points 4193 4194 Not Collective 4195 4196 Input Parameters: 4197 + dm - The DMPlex object 4198 . numPoints - The number of input points for the meet 4199 - points - The input points 4200 4201 Output Parameters: 4202 + numCoveredPoints - The number of points in the meet 4203 - coveredPoints - The points in the meet 4204 4205 Level: intermediate 4206 4207 Note: Currently, this is restricted to a single level meet 4208 4209 Fortran Notes: 4210 Since it returns an array, this routine is only available in Fortran 90, and you must 4211 include petsc.h90 in your code. 4212 4213 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4214 4215 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 4216 @*/ 4217 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4218 { 4219 DM_Plex *mesh = (DM_Plex*) dm->data; 4220 PetscInt *meet[2]; 4221 PetscInt meetSize, i = 0; 4222 PetscInt dof, off, p, c, m; 4223 PetscErrorCode ierr; 4224 4225 PetscFunctionBegin; 4226 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4227 PetscValidPointer(points, 3); 4228 PetscValidPointer(numCoveringPoints, 4); 4229 PetscValidPointer(coveringPoints, 5); 4230 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4231 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4232 /* Copy in cone of first point */ 4233 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 4234 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 4235 for (meetSize = 0; meetSize < dof; ++meetSize) { 4236 meet[i][meetSize] = mesh->cones[off+meetSize]; 4237 } 4238 /* Check each successive cone */ 4239 for (p = 1; p < numPoints; ++p) { 4240 PetscInt newMeetSize = 0; 4241 4242 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 4243 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 4244 for (c = 0; c < dof; ++c) { 4245 const PetscInt point = mesh->cones[off+c]; 4246 4247 for (m = 0; m < meetSize; ++m) { 4248 if (point == meet[i][m]) { 4249 meet[1-i][newMeetSize++] = point; 4250 break; 4251 } 4252 } 4253 } 4254 meetSize = newMeetSize; 4255 i = 1-i; 4256 } 4257 *numCoveringPoints = meetSize; 4258 *coveringPoints = meet[i]; 4259 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4260 PetscFunctionReturn(0); 4261 } 4262 4263 /*@C 4264 DMPlexRestoreMeet - Restore an array for the meet of the set of points 4265 4266 Not Collective 4267 4268 Input Parameters: 4269 + dm - The DMPlex object 4270 . numPoints - The number of input points for the meet 4271 - points - The input points 4272 4273 Output Parameters: 4274 + numCoveredPoints - The number of points in the meet 4275 - coveredPoints - The points in the meet 4276 4277 Level: intermediate 4278 4279 Fortran Notes: 4280 Since it returns an array, this routine is only available in Fortran 90, and you must 4281 include petsc.h90 in your code. 4282 4283 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4284 4285 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 4286 @*/ 4287 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4288 { 4289 PetscErrorCode ierr; 4290 4291 PetscFunctionBegin; 4292 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4293 if (points) PetscValidIntPointer(points,3); 4294 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4295 PetscValidPointer(coveredPoints,5); 4296 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4297 if (numCoveredPoints) *numCoveredPoints = 0; 4298 PetscFunctionReturn(0); 4299 } 4300 4301 /*@C 4302 DMPlexGetFullMeet - Get an array for the meet of the set of points 4303 4304 Not Collective 4305 4306 Input Parameters: 4307 + dm - The DMPlex object 4308 . numPoints - The number of input points for the meet 4309 - points - The input points 4310 4311 Output Parameters: 4312 + numCoveredPoints - The number of points in the meet 4313 - coveredPoints - The points in the meet 4314 4315 Level: intermediate 4316 4317 Fortran Notes: 4318 Since it returns an array, this routine is only available in Fortran 90, and you must 4319 include petsc.h90 in your code. 4320 4321 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4322 4323 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 4324 @*/ 4325 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4326 { 4327 DM_Plex *mesh = (DM_Plex*) dm->data; 4328 PetscInt *offsets, **closures; 4329 PetscInt *meet[2]; 4330 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 4331 PetscInt p, h, c, m, mc; 4332 PetscErrorCode ierr; 4333 4334 PetscFunctionBegin; 4335 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4336 PetscValidPointer(points, 3); 4337 PetscValidPointer(numCoveredPoints, 4); 4338 PetscValidPointer(coveredPoints, 5); 4339 4340 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 4341 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 4342 ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4343 mc = mesh->maxConeSize; 4344 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 4345 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4346 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4347 4348 for (p = 0; p < numPoints; ++p) { 4349 PetscInt closureSize; 4350 4351 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 4352 4353 offsets[p*(height+2)+0] = 0; 4354 for (h = 0; h < height+1; ++h) { 4355 PetscInt pStart, pEnd, i; 4356 4357 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 4358 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4359 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4360 offsets[p*(height+2)+h+1] = i; 4361 break; 4362 } 4363 } 4364 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4365 } 4366 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); 4367 } 4368 for (h = 0; h < height+1; ++h) { 4369 PetscInt dof; 4370 4371 /* Copy in cone of first point */ 4372 dof = offsets[h+1] - offsets[h]; 4373 for (meetSize = 0; meetSize < dof; ++meetSize) { 4374 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4375 } 4376 /* Check each successive cone */ 4377 for (p = 1; p < numPoints && meetSize; ++p) { 4378 PetscInt newMeetSize = 0; 4379 4380 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4381 for (c = 0; c < dof; ++c) { 4382 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4383 4384 for (m = 0; m < meetSize; ++m) { 4385 if (point == meet[i][m]) { 4386 meet[1-i][newMeetSize++] = point; 4387 break; 4388 } 4389 } 4390 } 4391 meetSize = newMeetSize; 4392 i = 1-i; 4393 } 4394 if (meetSize) break; 4395 } 4396 *numCoveredPoints = meetSize; 4397 *coveredPoints = meet[i]; 4398 for (p = 0; p < numPoints; ++p) { 4399 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 4400 } 4401 ierr = PetscFree(closures);CHKERRQ(ierr); 4402 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4403 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4404 PetscFunctionReturn(0); 4405 } 4406 4407 /*@C 4408 DMPlexEqual - Determine if two DMs have the same topology 4409 4410 Not Collective 4411 4412 Input Parameters: 4413 + dmA - A DMPlex object 4414 - dmB - A DMPlex object 4415 4416 Output Parameters: 4417 . equal - PETSC_TRUE if the topologies are identical 4418 4419 Level: intermediate 4420 4421 Notes: 4422 We are not solving graph isomorphism, so we do not permutation. 4423 4424 .seealso: DMPlexGetCone() 4425 @*/ 4426 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 4427 { 4428 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 4429 PetscErrorCode ierr; 4430 4431 PetscFunctionBegin; 4432 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 4433 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4434 PetscValidPointer(equal, 3); 4435 4436 *equal = PETSC_FALSE; 4437 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 4438 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 4439 if (depth != depthB) PetscFunctionReturn(0); 4440 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 4441 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 4442 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 4443 for (p = pStart; p < pEnd; ++p) { 4444 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 4445 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 4446 4447 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 4448 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 4449 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 4450 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 4451 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 4452 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 4453 if (coneSize != coneSizeB) PetscFunctionReturn(0); 4454 for (c = 0; c < coneSize; ++c) { 4455 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 4456 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 4457 } 4458 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 4459 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 4460 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 4461 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 4462 if (supportSize != supportSizeB) PetscFunctionReturn(0); 4463 for (s = 0; s < supportSize; ++s) { 4464 if (support[s] != supportB[s]) PetscFunctionReturn(0); 4465 } 4466 } 4467 *equal = PETSC_TRUE; 4468 PetscFunctionReturn(0); 4469 } 4470 4471 /*@C 4472 DMPlexGetNumFaceVertices - Returns the number of vertices on a face 4473 4474 Not Collective 4475 4476 Input Parameters: 4477 + dm - The DMPlex 4478 . cellDim - The cell dimension 4479 - numCorners - The number of vertices on a cell 4480 4481 Output Parameters: 4482 . numFaceVertices - The number of vertices on a face 4483 4484 Level: developer 4485 4486 Notes: 4487 Of course this can only work for a restricted set of symmetric shapes 4488 4489 .seealso: DMPlexGetCone() 4490 @*/ 4491 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4492 { 4493 MPI_Comm comm; 4494 PetscErrorCode ierr; 4495 4496 PetscFunctionBegin; 4497 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4498 PetscValidPointer(numFaceVertices,4); 4499 switch (cellDim) { 4500 case 0: 4501 *numFaceVertices = 0; 4502 break; 4503 case 1: 4504 *numFaceVertices = 1; 4505 break; 4506 case 2: 4507 switch (numCorners) { 4508 case 3: /* triangle */ 4509 *numFaceVertices = 2; /* Edge has 2 vertices */ 4510 break; 4511 case 4: /* quadrilateral */ 4512 *numFaceVertices = 2; /* Edge has 2 vertices */ 4513 break; 4514 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 4515 *numFaceVertices = 3; /* Edge has 3 vertices */ 4516 break; 4517 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 4518 *numFaceVertices = 3; /* Edge has 3 vertices */ 4519 break; 4520 default: 4521 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4522 } 4523 break; 4524 case 3: 4525 switch (numCorners) { 4526 case 4: /* tetradehdron */ 4527 *numFaceVertices = 3; /* Face has 3 vertices */ 4528 break; 4529 case 6: /* tet cohesive cells */ 4530 *numFaceVertices = 4; /* Face has 4 vertices */ 4531 break; 4532 case 8: /* hexahedron */ 4533 *numFaceVertices = 4; /* Face has 4 vertices */ 4534 break; 4535 case 9: /* tet cohesive Lagrange cells */ 4536 *numFaceVertices = 6; /* Face has 6 vertices */ 4537 break; 4538 case 10: /* quadratic tetrahedron */ 4539 *numFaceVertices = 6; /* Face has 6 vertices */ 4540 break; 4541 case 12: /* hex cohesive Lagrange cells */ 4542 *numFaceVertices = 6; /* Face has 6 vertices */ 4543 break; 4544 case 18: /* quadratic tet cohesive Lagrange cells */ 4545 *numFaceVertices = 6; /* Face has 6 vertices */ 4546 break; 4547 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 4548 *numFaceVertices = 9; /* Face has 9 vertices */ 4549 break; 4550 default: 4551 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4552 } 4553 break; 4554 default: 4555 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 4556 } 4557 PetscFunctionReturn(0); 4558 } 4559 4560 /*@ 4561 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4562 4563 Not Collective 4564 4565 Input Parameter: 4566 . dm - The DMPlex object 4567 4568 Output Parameter: 4569 . depthLabel - The DMLabel recording point depth 4570 4571 Level: developer 4572 4573 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), 4574 @*/ 4575 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4576 { 4577 PetscFunctionBegin; 4578 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4579 PetscValidPointer(depthLabel, 2); 4580 *depthLabel = dm->depthLabel; 4581 PetscFunctionReturn(0); 4582 } 4583 4584 /*@ 4585 DMPlexGetDepth - Get the depth of the DAG representing this mesh 4586 4587 Not Collective 4588 4589 Input Parameter: 4590 . dm - The DMPlex object 4591 4592 Output Parameter: 4593 . depth - The number of strata (breadth first levels) in the DAG 4594 4595 Level: developer 4596 4597 Notes: 4598 This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4599 The point depth is described more in detail in DMPlexGetDepthStratum(). 4600 An empty mesh gives -1. 4601 4602 .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize() 4603 @*/ 4604 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4605 { 4606 DMLabel label; 4607 PetscInt d = 0; 4608 PetscErrorCode ierr; 4609 4610 PetscFunctionBegin; 4611 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4612 PetscValidPointer(depth, 2); 4613 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4614 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 4615 *depth = d-1; 4616 PetscFunctionReturn(0); 4617 } 4618 4619 /*@ 4620 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4621 4622 Not Collective 4623 4624 Input Parameters: 4625 + dm - The DMPlex object 4626 - stratumValue - The requested depth 4627 4628 Output Parameters: 4629 + start - The first point at this depth 4630 - end - One beyond the last point at this depth 4631 4632 Notes: 4633 Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4634 often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4635 higher dimension, e.g., "edges". 4636 4637 Level: developer 4638 4639 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate() 4640 @*/ 4641 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4642 { 4643 DMLabel label; 4644 PetscInt pStart, pEnd; 4645 PetscErrorCode ierr; 4646 4647 PetscFunctionBegin; 4648 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4649 if (start) {PetscValidPointer(start, 3); *start = 0;} 4650 if (end) {PetscValidPointer(end, 4); *end = 0;} 4651 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4652 if (pStart == pEnd) PetscFunctionReturn(0); 4653 if (stratumValue < 0) { 4654 if (start) *start = pStart; 4655 if (end) *end = pEnd; 4656 PetscFunctionReturn(0); 4657 } 4658 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4659 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4660 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 4661 PetscFunctionReturn(0); 4662 } 4663 4664 /*@ 4665 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4666 4667 Not Collective 4668 4669 Input Parameters: 4670 + dm - The DMPlex object 4671 - stratumValue - The requested height 4672 4673 Output Parameters: 4674 + start - The first point at this height 4675 - end - One beyond the last point at this height 4676 4677 Notes: 4678 Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4679 points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4680 stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4681 4682 Level: developer 4683 4684 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight() 4685 @*/ 4686 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4687 { 4688 DMLabel label; 4689 PetscInt depth, pStart, pEnd; 4690 PetscErrorCode ierr; 4691 4692 PetscFunctionBegin; 4693 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4694 if (start) {PetscValidPointer(start, 3); *start = 0;} 4695 if (end) {PetscValidPointer(end, 4); *end = 0;} 4696 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4697 if (pStart == pEnd) PetscFunctionReturn(0); 4698 if (stratumValue < 0) { 4699 if (start) *start = pStart; 4700 if (end) *end = pEnd; 4701 PetscFunctionReturn(0); 4702 } 4703 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4704 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4705 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 4706 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 4707 PetscFunctionReturn(0); 4708 } 4709 4710 /*@ 4711 DMPlexGetPointDepth - Get the depth of a given point 4712 4713 Not Collective 4714 4715 Input Parameters: 4716 + dm - The DMPlex object 4717 - point - The point 4718 4719 Output Parameter: 4720 . depth - The depth of the point 4721 4722 Level: intermediate 4723 4724 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight() 4725 @*/ 4726 PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4727 { 4728 PetscErrorCode ierr; 4729 4730 PetscFunctionBegin; 4731 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4732 PetscValidIntPointer(depth, 3); 4733 ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr); 4734 PetscFunctionReturn(0); 4735 } 4736 4737 /*@ 4738 DMPlexGetPointHeight - Get the height of a given point 4739 4740 Not Collective 4741 4742 Input Parameters: 4743 + dm - The DMPlex object 4744 - point - The point 4745 4746 Output Parameter: 4747 . height - The height of the point 4748 4749 Level: intermediate 4750 4751 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth() 4752 @*/ 4753 PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 4754 { 4755 PetscInt n, pDepth; 4756 PetscErrorCode ierr; 4757 4758 PetscFunctionBegin; 4759 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4760 PetscValidIntPointer(height, 3); 4761 ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr); 4762 ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr); 4763 *height = n - 1 - pDepth; /* DAG depth is n-1 */ 4764 PetscFunctionReturn(0); 4765 } 4766 4767 /*@ 4768 DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4769 4770 Not Collective 4771 4772 Input Parameter: 4773 . dm - The DMPlex object 4774 4775 Output Parameter: 4776 . celltypeLabel - The DMLabel recording cell polytope type 4777 4778 Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4779 DMCreateLabel(dm, "celltype") beforehand. 4780 4781 Level: developer 4782 4783 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel() 4784 @*/ 4785 PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4786 { 4787 PetscErrorCode ierr; 4788 4789 PetscFunctionBegin; 4790 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4791 PetscValidPointer(celltypeLabel, 2); 4792 if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);} 4793 *celltypeLabel = dm->celltypeLabel; 4794 PetscFunctionReturn(0); 4795 } 4796 4797 /*@ 4798 DMPlexGetCellType - Get the polytope type of a given cell 4799 4800 Not Collective 4801 4802 Input Parameters: 4803 + dm - The DMPlex object 4804 - cell - The cell 4805 4806 Output Parameter: 4807 . celltype - The polytope type of the cell 4808 4809 Level: intermediate 4810 4811 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth() 4812 @*/ 4813 PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4814 { 4815 DMLabel label; 4816 PetscInt ct; 4817 PetscErrorCode ierr; 4818 4819 PetscFunctionBegin; 4820 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4821 PetscValidPointer(celltype, 3); 4822 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4823 ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr); 4824 if (ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell); 4825 *celltype = (DMPolytopeType) ct; 4826 PetscFunctionReturn(0); 4827 } 4828 4829 /*@ 4830 DMPlexSetCellType - Set the polytope type of a given cell 4831 4832 Not Collective 4833 4834 Input Parameters: 4835 + dm - The DMPlex object 4836 . cell - The cell 4837 - celltype - The polytope type of the cell 4838 4839 Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 4840 is executed. This function will override the computed type. However, if automatic classification will not succeed 4841 and a user wants to manually specify all types, the classification must be disabled by calling 4842 DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 4843 4844 Level: advanced 4845 4846 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel() 4847 @*/ 4848 PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 4849 { 4850 DMLabel label; 4851 PetscErrorCode ierr; 4852 4853 PetscFunctionBegin; 4854 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4855 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4856 ierr = DMLabelSetValue(label, cell, celltype);CHKERRQ(ierr); 4857 PetscFunctionReturn(0); 4858 } 4859 4860 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 4861 { 4862 PetscSection section, s; 4863 Mat m; 4864 PetscInt maxHeight; 4865 PetscErrorCode ierr; 4866 4867 PetscFunctionBegin; 4868 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 4869 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 4870 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 4871 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 4872 ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr); 4873 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 4874 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 4875 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 4876 ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr); 4877 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 4878 ierr = MatDestroy(&m);CHKERRQ(ierr); 4879 4880 ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr); 4881 ierr = DMCreateDS(*cdm);CHKERRQ(ierr); 4882 PetscFunctionReturn(0); 4883 } 4884 4885 PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 4886 { 4887 Vec coordsLocal; 4888 DM coordsDM; 4889 PetscErrorCode ierr; 4890 4891 PetscFunctionBegin; 4892 *field = NULL; 4893 ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr); 4894 ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr); 4895 if (coordsLocal && coordsDM) { 4896 ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr); 4897 } 4898 PetscFunctionReturn(0); 4899 } 4900 4901 /*@C 4902 DMPlexGetConeSection - Return a section which describes the layout of cone data 4903 4904 Not Collective 4905 4906 Input Parameters: 4907 . dm - The DMPlex object 4908 4909 Output Parameter: 4910 . section - The PetscSection object 4911 4912 Level: developer 4913 4914 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 4915 @*/ 4916 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 4917 { 4918 DM_Plex *mesh = (DM_Plex*) dm->data; 4919 4920 PetscFunctionBegin; 4921 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4922 if (section) *section = mesh->coneSection; 4923 PetscFunctionReturn(0); 4924 } 4925 4926 /*@C 4927 DMPlexGetSupportSection - Return a section which describes the layout of support data 4928 4929 Not Collective 4930 4931 Input Parameters: 4932 . dm - The DMPlex object 4933 4934 Output Parameter: 4935 . section - The PetscSection object 4936 4937 Level: developer 4938 4939 .seealso: DMPlexGetConeSection() 4940 @*/ 4941 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 4942 { 4943 DM_Plex *mesh = (DM_Plex*) dm->data; 4944 4945 PetscFunctionBegin; 4946 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4947 if (section) *section = mesh->supportSection; 4948 PetscFunctionReturn(0); 4949 } 4950 4951 /*@C 4952 DMPlexGetCones - Return cone data 4953 4954 Not Collective 4955 4956 Input Parameters: 4957 . dm - The DMPlex object 4958 4959 Output Parameter: 4960 . cones - The cone for each point 4961 4962 Level: developer 4963 4964 .seealso: DMPlexGetConeSection() 4965 @*/ 4966 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 4967 { 4968 DM_Plex *mesh = (DM_Plex*) dm->data; 4969 4970 PetscFunctionBegin; 4971 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4972 if (cones) *cones = mesh->cones; 4973 PetscFunctionReturn(0); 4974 } 4975 4976 /*@C 4977 DMPlexGetConeOrientations - Return cone orientation data 4978 4979 Not Collective 4980 4981 Input Parameters: 4982 . dm - The DMPlex object 4983 4984 Output Parameter: 4985 . coneOrientations - The array of cone orientations for all points 4986 4987 Level: developer 4988 4989 Notes: 4990 The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation(). 4991 4992 The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation(). 4993 4994 .seealso: DMPlexGetConeSection(), DMPlexGetConeOrientation() 4995 @*/ 4996 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 4997 { 4998 DM_Plex *mesh = (DM_Plex*) dm->data; 4999 5000 PetscFunctionBegin; 5001 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5002 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 5003 PetscFunctionReturn(0); 5004 } 5005 5006 /******************************** FEM Support **********************************/ 5007 5008 /* 5009 Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 5010 representing a line in the section. 5011 */ 5012 static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 5013 { 5014 PetscErrorCode ierr; 5015 5016 PetscFunctionBeginHot; 5017 ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr); 5018 if (line < 0) { 5019 *k = 0; 5020 *Nc = 0; 5021 } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 5022 *k = 1; 5023 } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 5024 /* An order k SEM disc has k-1 dofs on an edge */ 5025 ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr); 5026 *k = *k / *Nc + 1; 5027 } 5028 PetscFunctionReturn(0); 5029 } 5030 5031 /*@ 5032 5033 DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5034 lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 5035 section provided (or the section of the DM). 5036 5037 Input Parameters: 5038 + dm - The DM 5039 . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 5040 - section - The PetscSection to reorder, or NULL for the default section 5041 5042 Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5043 degree of the basis. 5044 5045 Example: 5046 A typical interpolated single-quad mesh might order points as 5047 .vb 5048 [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5049 5050 v4 -- e6 -- v3 5051 | | 5052 e7 c0 e8 5053 | | 5054 v1 -- e5 -- v2 5055 .ve 5056 5057 (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5058 dofs in the order of points, e.g., 5059 .vb 5060 c0 -> [0,1,2,3] 5061 v1 -> [4] 5062 ... 5063 e5 -> [8, 9] 5064 .ve 5065 5066 which corresponds to the dofs 5067 .vb 5068 6 10 11 7 5069 13 2 3 15 5070 12 0 1 14 5071 4 8 9 5 5072 .ve 5073 5074 The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5075 .vb 5076 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5077 .ve 5078 5079 After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5080 .vb 5081 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5082 .ve 5083 5084 Level: developer 5085 5086 .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection() 5087 @*/ 5088 PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5089 { 5090 DMLabel label; 5091 PetscInt dim, depth = -1, eStart = -1, Nf; 5092 PetscBool vertexchart; 5093 PetscErrorCode ierr; 5094 5095 PetscFunctionBegin; 5096 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5097 if (dim < 1) PetscFunctionReturn(0); 5098 if (point < 0) { 5099 PetscInt sStart,sEnd; 5100 5101 ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr); 5102 point = sEnd-sStart ? sStart : point; 5103 } 5104 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 5105 if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); } 5106 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5107 if (depth == 1) {eStart = point;} 5108 else if (depth == dim) { 5109 const PetscInt *cone; 5110 5111 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5112 if (dim == 2) eStart = cone[0]; 5113 else if (dim == 3) { 5114 const PetscInt *cone2; 5115 ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 5116 eStart = cone2[0]; 5117 } 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); 5118 } 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); 5119 { /* Determine whether the chart covers all points or just vertices. */ 5120 PetscInt pStart,pEnd,cStart,cEnd; 5121 ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr); 5122 ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr); 5123 if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Just vertices */ 5124 else vertexchart = PETSC_FALSE; /* Assume all interpolated points are in chart */ 5125 } 5126 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5127 for (PetscInt d=1; d<=dim; d++) { 5128 PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5129 PetscInt *perm; 5130 5131 for (f = 0; f < Nf; ++f) { 5132 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5133 size += PetscPowInt(k+1, d)*Nc; 5134 } 5135 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 5136 for (f = 0; f < Nf; ++f) { 5137 switch (d) { 5138 case 1: 5139 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5140 /* 5141 Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5142 We want [ vtx0; edge of length k-1; vtx1 ] 5143 */ 5144 for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5145 for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5146 for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5147 foffset = offset; 5148 break; 5149 case 2: 5150 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 5151 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5152 /* The SEM order is 5153 5154 v_lb, {e_b}, v_rb, 5155 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 5156 v_lt, reverse {e_t}, v_rt 5157 */ 5158 { 5159 const PetscInt of = 0; 5160 const PetscInt oeb = of + PetscSqr(k-1); 5161 const PetscInt oer = oeb + (k-1); 5162 const PetscInt oet = oer + (k-1); 5163 const PetscInt oel = oet + (k-1); 5164 const PetscInt ovlb = oel + (k-1); 5165 const PetscInt ovrb = ovlb + 1; 5166 const PetscInt ovrt = ovrb + 1; 5167 const PetscInt ovlt = ovrt + 1; 5168 PetscInt o; 5169 5170 /* bottom */ 5171 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 5172 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5173 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 5174 /* middle */ 5175 for (i = 0; i < k-1; ++i) { 5176 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 5177 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; 5178 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 5179 } 5180 /* top */ 5181 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 5182 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5183 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 5184 foffset = offset; 5185 } 5186 break; 5187 case 3: 5188 /* The original hex closure is 5189 5190 {c, 5191 f_b, f_t, f_f, f_b, f_r, f_l, 5192 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 5193 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 5194 */ 5195 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5196 /* The SEM order is 5197 Bottom Slice 5198 v_blf, {e^{(k-1)-n}_bf}, v_brf, 5199 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 5200 v_blb, {e_bb}, v_brb, 5201 5202 Middle Slice (j) 5203 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 5204 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 5205 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 5206 5207 Top Slice 5208 v_tlf, {e_tf}, v_trf, 5209 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 5210 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 5211 */ 5212 { 5213 const PetscInt oc = 0; 5214 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 5215 const PetscInt oft = ofb + PetscSqr(k-1); 5216 const PetscInt off = oft + PetscSqr(k-1); 5217 const PetscInt ofk = off + PetscSqr(k-1); 5218 const PetscInt ofr = ofk + PetscSqr(k-1); 5219 const PetscInt ofl = ofr + PetscSqr(k-1); 5220 const PetscInt oebl = ofl + PetscSqr(k-1); 5221 const PetscInt oebb = oebl + (k-1); 5222 const PetscInt oebr = oebb + (k-1); 5223 const PetscInt oebf = oebr + (k-1); 5224 const PetscInt oetf = oebf + (k-1); 5225 const PetscInt oetr = oetf + (k-1); 5226 const PetscInt oetb = oetr + (k-1); 5227 const PetscInt oetl = oetb + (k-1); 5228 const PetscInt oerf = oetl + (k-1); 5229 const PetscInt oelf = oerf + (k-1); 5230 const PetscInt oelb = oelf + (k-1); 5231 const PetscInt oerb = oelb + (k-1); 5232 const PetscInt ovblf = oerb + (k-1); 5233 const PetscInt ovblb = ovblf + 1; 5234 const PetscInt ovbrb = ovblb + 1; 5235 const PetscInt ovbrf = ovbrb + 1; 5236 const PetscInt ovtlf = ovbrf + 1; 5237 const PetscInt ovtrf = ovtlf + 1; 5238 const PetscInt ovtrb = ovtrf + 1; 5239 const PetscInt ovtlb = ovtrb + 1; 5240 PetscInt o, n; 5241 5242 /* Bottom Slice */ 5243 /* bottom */ 5244 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 5245 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5246 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 5247 /* middle */ 5248 for (i = 0; i < k-1; ++i) { 5249 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5250 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;} 5251 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 5252 } 5253 /* top */ 5254 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 5255 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5256 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 5257 5258 /* Middle Slice */ 5259 for (j = 0; j < k-1; ++j) { 5260 /* bottom */ 5261 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 5262 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; 5263 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 5264 /* middle */ 5265 for (i = 0; i < k-1; ++i) { 5266 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 5267 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; 5268 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 5269 } 5270 /* top */ 5271 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 5272 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; 5273 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 5274 } 5275 5276 /* Top Slice */ 5277 /* bottom */ 5278 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 5279 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5280 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 5281 /* middle */ 5282 for (i = 0; i < k-1; ++i) { 5283 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 5284 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 5285 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 5286 } 5287 /* top */ 5288 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 5289 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5290 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 5291 5292 foffset = offset; 5293 } 5294 break; 5295 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d); 5296 } 5297 } 5298 if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 5299 /* Check permutation */ 5300 { 5301 PetscInt *check; 5302 5303 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 5304 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]);} 5305 for (i = 0; i < size; ++i) check[perm[i]] = i; 5306 for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 5307 ierr = PetscFree(check);CHKERRQ(ierr); 5308 } 5309 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 5310 } 5311 PetscFunctionReturn(0); 5312 } 5313 5314 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5315 { 5316 PetscDS prob; 5317 PetscInt depth, Nf, h; 5318 DMLabel label; 5319 PetscErrorCode ierr; 5320 5321 PetscFunctionBeginHot; 5322 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 5323 Nf = prob->Nf; 5324 label = dm->depthLabel; 5325 *dspace = NULL; 5326 if (field < Nf) { 5327 PetscObject disc = prob->disc[field]; 5328 5329 if (disc->classid == PETSCFE_CLASSID) { 5330 PetscDualSpace dsp; 5331 5332 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 5333 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 5334 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 5335 h = depth - 1 - h; 5336 if (h) { 5337 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 5338 } else { 5339 *dspace = dsp; 5340 } 5341 } 5342 } 5343 PetscFunctionReturn(0); 5344 } 5345 5346 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5347 { 5348 PetscScalar *array, *vArray; 5349 const PetscInt *cone, *coneO; 5350 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5351 PetscErrorCode ierr; 5352 5353 PetscFunctionBeginHot; 5354 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5355 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5356 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5357 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5358 if (!values || !*values) { 5359 if ((point >= pStart) && (point < pEnd)) { 5360 PetscInt dof; 5361 5362 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5363 size += dof; 5364 } 5365 for (p = 0; p < numPoints; ++p) { 5366 const PetscInt cp = cone[p]; 5367 PetscInt dof; 5368 5369 if ((cp < pStart) || (cp >= pEnd)) continue; 5370 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5371 size += dof; 5372 } 5373 if (!values) { 5374 if (csize) *csize = size; 5375 PetscFunctionReturn(0); 5376 } 5377 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 5378 } else { 5379 array = *values; 5380 } 5381 size = 0; 5382 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 5383 if ((point >= pStart) && (point < pEnd)) { 5384 PetscInt dof, off, d; 5385 PetscScalar *varr; 5386 5387 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5388 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5389 varr = &vArray[off]; 5390 for (d = 0; d < dof; ++d, ++offset) { 5391 array[offset] = varr[d]; 5392 } 5393 size += dof; 5394 } 5395 for (p = 0; p < numPoints; ++p) { 5396 const PetscInt cp = cone[p]; 5397 PetscInt o = coneO[p]; 5398 PetscInt dof, off, d; 5399 PetscScalar *varr; 5400 5401 if ((cp < pStart) || (cp >= pEnd)) continue; 5402 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5403 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 5404 varr = &vArray[off]; 5405 if (o >= 0) { 5406 for (d = 0; d < dof; ++d, ++offset) { 5407 array[offset] = varr[d]; 5408 } 5409 } else { 5410 for (d = dof-1; d >= 0; --d, ++offset) { 5411 array[offset] = varr[d]; 5412 } 5413 } 5414 size += dof; 5415 } 5416 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 5417 if (!*values) { 5418 if (csize) *csize = size; 5419 *values = array; 5420 } else { 5421 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5422 *csize = size; 5423 } 5424 PetscFunctionReturn(0); 5425 } 5426 5427 /* Compress out points not in the section */ 5428 PETSC_STATIC_INLINE PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 5429 { 5430 const PetscInt np = *numPoints; 5431 PetscInt pStart, pEnd, p, q; 5432 PetscErrorCode ierr; 5433 5434 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5435 for (p = 0, q = 0; p < np; ++p) { 5436 const PetscInt r = points[p*2]; 5437 if ((r >= pStart) && (r < pEnd)) { 5438 points[q*2] = r; 5439 points[q*2+1] = points[p*2+1]; 5440 ++q; 5441 } 5442 } 5443 *numPoints = q; 5444 return 0; 5445 } 5446 5447 /* Compressed closure does not apply closure permutation */ 5448 PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5449 { 5450 const PetscInt *cla = NULL; 5451 PetscInt np, *pts = NULL; 5452 PetscErrorCode ierr; 5453 5454 PetscFunctionBeginHot; 5455 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 5456 if (*clPoints) { 5457 PetscInt dof, off; 5458 5459 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 5460 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 5461 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 5462 np = dof/2; 5463 pts = (PetscInt *) &cla[off]; 5464 } else { 5465 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 5466 ierr = CompressPoints_Private(section, &np, pts);CHKERRQ(ierr); 5467 } 5468 *numPoints = np; 5469 *points = pts; 5470 *clp = cla; 5471 PetscFunctionReturn(0); 5472 } 5473 5474 PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5475 { 5476 PetscErrorCode ierr; 5477 5478 PetscFunctionBeginHot; 5479 if (!*clPoints) { 5480 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 5481 } else { 5482 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 5483 } 5484 *numPoints = 0; 5485 *points = NULL; 5486 *clSec = NULL; 5487 *clPoints = NULL; 5488 *clp = NULL; 5489 PetscFunctionReturn(0); 5490 } 5491 5492 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[]) 5493 { 5494 PetscInt offset = 0, p; 5495 const PetscInt **perms = NULL; 5496 const PetscScalar **flips = NULL; 5497 PetscErrorCode ierr; 5498 5499 PetscFunctionBeginHot; 5500 *size = 0; 5501 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5502 for (p = 0; p < numPoints; p++) { 5503 const PetscInt point = points[2*p]; 5504 const PetscInt *perm = perms ? perms[p] : NULL; 5505 const PetscScalar *flip = flips ? flips[p] : NULL; 5506 PetscInt dof, off, d; 5507 const PetscScalar *varr; 5508 5509 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5510 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5511 varr = &vArray[off]; 5512 if (clperm) { 5513 if (perm) { 5514 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 5515 } else { 5516 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 5517 } 5518 if (flip) { 5519 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 5520 } 5521 } else { 5522 if (perm) { 5523 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 5524 } else { 5525 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 5526 } 5527 if (flip) { 5528 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 5529 } 5530 } 5531 offset += dof; 5532 } 5533 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5534 *size = offset; 5535 PetscFunctionReturn(0); 5536 } 5537 5538 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[]) 5539 { 5540 PetscInt offset = 0, f; 5541 PetscErrorCode ierr; 5542 5543 PetscFunctionBeginHot; 5544 *size = 0; 5545 for (f = 0; f < numFields; ++f) { 5546 PetscInt p; 5547 const PetscInt **perms = NULL; 5548 const PetscScalar **flips = NULL; 5549 5550 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5551 for (p = 0; p < numPoints; p++) { 5552 const PetscInt point = points[2*p]; 5553 PetscInt fdof, foff, b; 5554 const PetscScalar *varr; 5555 const PetscInt *perm = perms ? perms[p] : NULL; 5556 const PetscScalar *flip = flips ? flips[p] : NULL; 5557 5558 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5559 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5560 varr = &vArray[foff]; 5561 if (clperm) { 5562 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 5563 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 5564 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 5565 } else { 5566 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 5567 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 5568 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 5569 } 5570 offset += fdof; 5571 } 5572 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5573 } 5574 *size = offset; 5575 PetscFunctionReturn(0); 5576 } 5577 5578 /*@C 5579 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5580 5581 Not collective 5582 5583 Input Parameters: 5584 + dm - The DM 5585 . section - The section describing the layout in v, or NULL to use the default section 5586 . v - The local vector 5587 - point - The point in the DM 5588 5589 Input/Output Parameters: 5590 + csize - The size of the input values array, or NULL; on output the number of values in the closure 5591 - values - An array to use for the values, or NULL to have it allocated automatically; 5592 if the user provided NULL, it is a borrowed array and should not be freed 5593 5594 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 5595 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 5596 $ assembly function, and a user may already have allocated storage for this operation. 5597 $ 5598 $ A typical use could be 5599 $ 5600 $ values = NULL; 5601 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5602 $ for (cl = 0; cl < clSize; ++cl) { 5603 $ <Compute on closure> 5604 $ } 5605 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5606 $ 5607 $ or 5608 $ 5609 $ PetscMalloc1(clMaxSize, &values); 5610 $ for (p = pStart; p < pEnd; ++p) { 5611 $ clSize = clMaxSize; 5612 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5613 $ for (cl = 0; cl < clSize; ++cl) { 5614 $ <Compute on closure> 5615 $ } 5616 $ } 5617 $ PetscFree(values); 5618 5619 Fortran Notes: 5620 Since it returns an array, this routine is only available in Fortran 90, and you must 5621 include petsc.h90 in your code. 5622 5623 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5624 5625 Level: intermediate 5626 5627 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5628 @*/ 5629 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5630 { 5631 PetscSection clSection; 5632 IS clPoints; 5633 PetscInt *points = NULL; 5634 const PetscInt *clp, *perm; 5635 PetscInt depth, numFields, numPoints, asize; 5636 PetscErrorCode ierr; 5637 5638 PetscFunctionBeginHot; 5639 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5640 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5641 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5642 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5643 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5644 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5645 if (depth == 1 && numFields < 2) { 5646 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5647 PetscFunctionReturn(0); 5648 } 5649 /* Get points */ 5650 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5651 /* Get sizes */ 5652 asize = 0; 5653 for (PetscInt p = 0; p < numPoints*2; p += 2) { 5654 PetscInt dof; 5655 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5656 asize += dof; 5657 } 5658 if (values) { 5659 const PetscScalar *vArray; 5660 PetscInt size; 5661 5662 if (*values) { 5663 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); 5664 } else {ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, values);CHKERRQ(ierr);} 5665 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm);CHKERRQ(ierr); 5666 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5667 /* Get values */ 5668 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values);CHKERRQ(ierr);} 5669 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values);CHKERRQ(ierr);} 5670 if (PetscUnlikely(asize != size)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size); 5671 /* Cleanup array */ 5672 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5673 } 5674 if (csize) *csize = asize; 5675 /* Cleanup points */ 5676 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5677 PetscFunctionReturn(0); 5678 } 5679 5680 PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5681 { 5682 DMLabel depthLabel; 5683 PetscSection clSection; 5684 IS clPoints; 5685 PetscScalar *array; 5686 const PetscScalar *vArray; 5687 PetscInt *points = NULL; 5688 const PetscInt *clp, *perm = NULL; 5689 PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5690 PetscErrorCode ierr; 5691 5692 PetscFunctionBeginHot; 5693 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5694 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5695 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5696 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5697 ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr); 5698 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 5699 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5700 if (mdepth == 1 && numFields < 2) { 5701 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5702 PetscFunctionReturn(0); 5703 } 5704 /* Get points */ 5705 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5706 for (clsize=0,p=0; p<Np; p++) { 5707 PetscInt dof; 5708 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 5709 clsize += dof; 5710 } 5711 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm);CHKERRQ(ierr); 5712 /* Filter points */ 5713 for (p = 0; p < numPoints*2; p += 2) { 5714 PetscInt dep; 5715 5716 ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr); 5717 if (dep != depth) continue; 5718 points[Np*2+0] = points[p]; 5719 points[Np*2+1] = points[p+1]; 5720 ++Np; 5721 } 5722 /* Get array */ 5723 if (!values || !*values) { 5724 PetscInt asize = 0, dof; 5725 5726 for (p = 0; p < Np*2; p += 2) { 5727 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5728 asize += dof; 5729 } 5730 if (!values) { 5731 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5732 if (csize) *csize = asize; 5733 PetscFunctionReturn(0); 5734 } 5735 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 5736 } else { 5737 array = *values; 5738 } 5739 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5740 /* Get values */ 5741 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 5742 else {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);} 5743 /* Cleanup points */ 5744 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5745 /* Cleanup array */ 5746 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5747 if (!*values) { 5748 if (csize) *csize = size; 5749 *values = array; 5750 } else { 5751 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5752 *csize = size; 5753 } 5754 PetscFunctionReturn(0); 5755 } 5756 5757 /*@C 5758 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5759 5760 Not collective 5761 5762 Input Parameters: 5763 + dm - The DM 5764 . section - The section describing the layout in v, or NULL to use the default section 5765 . v - The local vector 5766 . point - The point in the DM 5767 . csize - The number of values in the closure, or NULL 5768 - values - The array of values, which is a borrowed array and should not be freed 5769 5770 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 5771 5772 Fortran Notes: 5773 Since it returns an array, this routine is only available in Fortran 90, and you must 5774 include petsc.h90 in your code. 5775 5776 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5777 5778 Level: intermediate 5779 5780 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5781 @*/ 5782 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5783 { 5784 PetscInt size = 0; 5785 PetscErrorCode ierr; 5786 5787 PetscFunctionBegin; 5788 /* Should work without recalculating size */ 5789 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 5790 *values = NULL; 5791 PetscFunctionReturn(0); 5792 } 5793 5794 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 5795 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5796 5797 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[]) 5798 { 5799 PetscInt cdof; /* The number of constraints on this point */ 5800 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5801 PetscScalar *a; 5802 PetscInt off, cind = 0, k; 5803 PetscErrorCode ierr; 5804 5805 PetscFunctionBegin; 5806 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5807 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5808 a = &array[off]; 5809 if (!cdof || setBC) { 5810 if (clperm) { 5811 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 5812 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5813 } else { 5814 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 5815 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5816 } 5817 } else { 5818 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5819 if (clperm) { 5820 if (perm) {for (k = 0; k < dof; ++k) { 5821 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5822 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5823 } 5824 } else { 5825 for (k = 0; k < dof; ++k) { 5826 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5827 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5828 } 5829 } 5830 } else { 5831 if (perm) { 5832 for (k = 0; k < dof; ++k) { 5833 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5834 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5835 } 5836 } else { 5837 for (k = 0; k < dof; ++k) { 5838 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5839 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5840 } 5841 } 5842 } 5843 } 5844 PetscFunctionReturn(0); 5845 } 5846 5847 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[]) 5848 { 5849 PetscInt cdof; /* The number of constraints on this point */ 5850 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5851 PetscScalar *a; 5852 PetscInt off, cind = 0, k; 5853 PetscErrorCode ierr; 5854 5855 PetscFunctionBegin; 5856 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5857 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5858 a = &array[off]; 5859 if (cdof) { 5860 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5861 if (clperm) { 5862 if (perm) { 5863 for (k = 0; k < dof; ++k) { 5864 if ((cind < cdof) && (k == cdofs[cind])) { 5865 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5866 cind++; 5867 } 5868 } 5869 } else { 5870 for (k = 0; k < dof; ++k) { 5871 if ((cind < cdof) && (k == cdofs[cind])) { 5872 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5873 cind++; 5874 } 5875 } 5876 } 5877 } else { 5878 if (perm) { 5879 for (k = 0; k < dof; ++k) { 5880 if ((cind < cdof) && (k == cdofs[cind])) { 5881 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5882 cind++; 5883 } 5884 } 5885 } else { 5886 for (k = 0; k < dof; ++k) { 5887 if ((cind < cdof) && (k == cdofs[cind])) { 5888 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5889 cind++; 5890 } 5891 } 5892 } 5893 } 5894 } 5895 PetscFunctionReturn(0); 5896 } 5897 5898 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[]) 5899 { 5900 PetscScalar *a; 5901 PetscInt fdof, foff, fcdof, foffset = *offset; 5902 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5903 PetscInt cind = 0, b; 5904 PetscErrorCode ierr; 5905 5906 PetscFunctionBegin; 5907 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5908 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 5909 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5910 a = &array[foff]; 5911 if (!fcdof || setBC) { 5912 if (clperm) { 5913 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 5914 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 5915 } else { 5916 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 5917 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 5918 } 5919 } else { 5920 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5921 if (clperm) { 5922 if (perm) { 5923 for (b = 0; b < fdof; b++) { 5924 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5925 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 5926 } 5927 } else { 5928 for (b = 0; b < fdof; b++) { 5929 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5930 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 5931 } 5932 } 5933 } else { 5934 if (perm) { 5935 for (b = 0; b < fdof; b++) { 5936 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5937 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 5938 } 5939 } else { 5940 for (b = 0; b < fdof; b++) { 5941 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5942 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 5943 } 5944 } 5945 } 5946 } 5947 *offset += fdof; 5948 PetscFunctionReturn(0); 5949 } 5950 5951 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[]) 5952 { 5953 PetscScalar *a; 5954 PetscInt fdof, foff, fcdof, foffset = *offset; 5955 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5956 PetscInt Nc, cind = 0, ncind = 0, b; 5957 PetscBool ncSet, fcSet; 5958 PetscErrorCode ierr; 5959 5960 PetscFunctionBegin; 5961 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 5962 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5963 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 5964 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5965 a = &array[foff]; 5966 if (fcdof) { 5967 /* We just override fcdof and fcdofs with Ncc and comps */ 5968 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5969 if (clperm) { 5970 if (perm) { 5971 if (comps) { 5972 for (b = 0; b < fdof; b++) { 5973 ncSet = fcSet = PETSC_FALSE; 5974 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5975 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5976 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 5977 } 5978 } else { 5979 for (b = 0; b < fdof; b++) { 5980 if ((cind < fcdof) && (b == fcdofs[cind])) { 5981 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 5982 ++cind; 5983 } 5984 } 5985 } 5986 } else { 5987 if (comps) { 5988 for (b = 0; b < fdof; b++) { 5989 ncSet = fcSet = PETSC_FALSE; 5990 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5991 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5992 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 5993 } 5994 } else { 5995 for (b = 0; b < fdof; b++) { 5996 if ((cind < fcdof) && (b == fcdofs[cind])) { 5997 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 5998 ++cind; 5999 } 6000 } 6001 } 6002 } 6003 } else { 6004 if (perm) { 6005 if (comps) { 6006 for (b = 0; b < fdof; b++) { 6007 ncSet = fcSet = PETSC_FALSE; 6008 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6009 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6010 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 6011 } 6012 } else { 6013 for (b = 0; b < fdof; b++) { 6014 if ((cind < fcdof) && (b == fcdofs[cind])) { 6015 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6016 ++cind; 6017 } 6018 } 6019 } 6020 } else { 6021 if (comps) { 6022 for (b = 0; b < fdof; b++) { 6023 ncSet = fcSet = PETSC_FALSE; 6024 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6025 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6026 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 6027 } 6028 } else { 6029 for (b = 0; b < fdof; b++) { 6030 if ((cind < fcdof) && (b == fcdofs[cind])) { 6031 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6032 ++cind; 6033 } 6034 } 6035 } 6036 } 6037 } 6038 } 6039 *offset += fdof; 6040 PetscFunctionReturn(0); 6041 } 6042 6043 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6044 { 6045 PetscScalar *array; 6046 const PetscInt *cone, *coneO; 6047 PetscInt pStart, pEnd, p, numPoints, off, dof; 6048 PetscErrorCode ierr; 6049 6050 PetscFunctionBeginHot; 6051 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6052 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 6053 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 6054 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 6055 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6056 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6057 const PetscInt cp = !p ? point : cone[p-1]; 6058 const PetscInt o = !p ? 0 : coneO[p-1]; 6059 6060 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 6061 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 6062 /* ADD_VALUES */ 6063 { 6064 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6065 PetscScalar *a; 6066 PetscInt cdof, coff, cind = 0, k; 6067 6068 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 6069 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 6070 a = &array[coff]; 6071 if (!cdof) { 6072 if (o >= 0) { 6073 for (k = 0; k < dof; ++k) { 6074 a[k] += values[off+k]; 6075 } 6076 } else { 6077 for (k = 0; k < dof; ++k) { 6078 a[k] += values[off+dof-k-1]; 6079 } 6080 } 6081 } else { 6082 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 6083 if (o >= 0) { 6084 for (k = 0; k < dof; ++k) { 6085 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6086 a[k] += values[off+k]; 6087 } 6088 } else { 6089 for (k = 0; k < dof; ++k) { 6090 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6091 a[k] += values[off+dof-k-1]; 6092 } 6093 } 6094 } 6095 } 6096 } 6097 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6098 PetscFunctionReturn(0); 6099 } 6100 6101 /*@C 6102 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6103 6104 Not collective 6105 6106 Input Parameters: 6107 + dm - The DM 6108 . section - The section describing the layout in v, or NULL to use the default section 6109 . v - The local vector 6110 . point - The point in the DM 6111 . values - The array of values 6112 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 6113 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 6114 6115 Fortran Notes: 6116 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6117 6118 Level: intermediate 6119 6120 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6121 @*/ 6122 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6123 { 6124 PetscSection clSection; 6125 IS clPoints; 6126 PetscScalar *array; 6127 PetscInt *points = NULL; 6128 const PetscInt *clp, *clperm = NULL; 6129 PetscInt depth, numFields, numPoints, p, clsize; 6130 PetscErrorCode ierr; 6131 6132 PetscFunctionBeginHot; 6133 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6134 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6135 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6136 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6137 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6138 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6139 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 6140 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 6141 PetscFunctionReturn(0); 6142 } 6143 /* Get points */ 6144 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6145 for (clsize=0,p=0; p<numPoints; p++) { 6146 PetscInt dof; 6147 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 6148 clsize += dof; 6149 } 6150 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 6151 /* Get array */ 6152 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6153 /* Get values */ 6154 if (numFields > 0) { 6155 PetscInt offset = 0, f; 6156 for (f = 0; f < numFields; ++f) { 6157 const PetscInt **perms = NULL; 6158 const PetscScalar **flips = NULL; 6159 6160 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6161 switch (mode) { 6162 case INSERT_VALUES: 6163 for (p = 0; p < numPoints; p++) { 6164 const PetscInt point = points[2*p]; 6165 const PetscInt *perm = perms ? perms[p] : NULL; 6166 const PetscScalar *flip = flips ? flips[p] : NULL; 6167 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6168 } break; 6169 case INSERT_ALL_VALUES: 6170 for (p = 0; p < numPoints; p++) { 6171 const PetscInt point = points[2*p]; 6172 const PetscInt *perm = perms ? perms[p] : NULL; 6173 const PetscScalar *flip = flips ? flips[p] : NULL; 6174 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6175 } break; 6176 case INSERT_BC_VALUES: 6177 for (p = 0; p < numPoints; p++) { 6178 const PetscInt point = points[2*p]; 6179 const PetscInt *perm = perms ? perms[p] : NULL; 6180 const PetscScalar *flip = flips ? flips[p] : NULL; 6181 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6182 } break; 6183 case ADD_VALUES: 6184 for (p = 0; p < numPoints; p++) { 6185 const PetscInt point = points[2*p]; 6186 const PetscInt *perm = perms ? perms[p] : NULL; 6187 const PetscScalar *flip = flips ? flips[p] : NULL; 6188 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6189 } break; 6190 case ADD_ALL_VALUES: 6191 for (p = 0; p < numPoints; p++) { 6192 const PetscInt point = points[2*p]; 6193 const PetscInt *perm = perms ? perms[p] : NULL; 6194 const PetscScalar *flip = flips ? flips[p] : NULL; 6195 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6196 } break; 6197 case ADD_BC_VALUES: 6198 for (p = 0; p < numPoints; p++) { 6199 const PetscInt point = points[2*p]; 6200 const PetscInt *perm = perms ? perms[p] : NULL; 6201 const PetscScalar *flip = flips ? flips[p] : NULL; 6202 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6203 } break; 6204 default: 6205 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6206 } 6207 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6208 } 6209 } else { 6210 PetscInt dof, off; 6211 const PetscInt **perms = NULL; 6212 const PetscScalar **flips = NULL; 6213 6214 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6215 switch (mode) { 6216 case INSERT_VALUES: 6217 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6218 const PetscInt point = points[2*p]; 6219 const PetscInt *perm = perms ? perms[p] : NULL; 6220 const PetscScalar *flip = flips ? flips[p] : NULL; 6221 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6222 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6223 } break; 6224 case INSERT_ALL_VALUES: 6225 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6226 const PetscInt point = points[2*p]; 6227 const PetscInt *perm = perms ? perms[p] : NULL; 6228 const PetscScalar *flip = flips ? flips[p] : NULL; 6229 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6230 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6231 } break; 6232 case INSERT_BC_VALUES: 6233 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6234 const PetscInt point = points[2*p]; 6235 const PetscInt *perm = perms ? perms[p] : NULL; 6236 const PetscScalar *flip = flips ? flips[p] : NULL; 6237 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6238 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6239 } break; 6240 case ADD_VALUES: 6241 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6242 const PetscInt point = points[2*p]; 6243 const PetscInt *perm = perms ? perms[p] : NULL; 6244 const PetscScalar *flip = flips ? flips[p] : NULL; 6245 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6246 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6247 } break; 6248 case ADD_ALL_VALUES: 6249 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6250 const PetscInt point = points[2*p]; 6251 const PetscInt *perm = perms ? perms[p] : NULL; 6252 const PetscScalar *flip = flips ? flips[p] : NULL; 6253 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6254 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6255 } break; 6256 case ADD_BC_VALUES: 6257 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6258 const PetscInt point = points[2*p]; 6259 const PetscInt *perm = perms ? perms[p] : NULL; 6260 const PetscScalar *flip = flips ? flips[p] : NULL; 6261 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6262 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6263 } break; 6264 default: 6265 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6266 } 6267 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6268 } 6269 /* Cleanup points */ 6270 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6271 /* Cleanup array */ 6272 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6273 PetscFunctionReturn(0); 6274 } 6275 6276 /* Check whether the given point is in the label. If not, update the offset to skip this point */ 6277 PETSC_STATIC_INLINE PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 6278 { 6279 PetscFunctionBegin; 6280 if (label) { 6281 PetscInt val, fdof; 6282 PetscErrorCode ierr; 6283 6284 /* There is a problem with this: 6285 Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that 6286 touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell. 6287 Thus I am only going to check val != -1, not val != labelId 6288 */ 6289 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 6290 if (val < 0) { 6291 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6292 *offset += fdof; 6293 PetscFunctionReturn(1); 6294 } 6295 } 6296 PetscFunctionReturn(0); 6297 } 6298 6299 /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 6300 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) 6301 { 6302 PetscSection clSection; 6303 IS clPoints; 6304 PetscScalar *array; 6305 PetscInt *points = NULL; 6306 const PetscInt *clp; 6307 PetscInt numFields, numPoints, p; 6308 PetscInt offset = 0, f; 6309 PetscErrorCode ierr; 6310 6311 PetscFunctionBeginHot; 6312 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6313 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6314 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6315 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6316 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6317 /* Get points */ 6318 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6319 /* Get array */ 6320 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6321 /* Get values */ 6322 for (f = 0; f < numFields; ++f) { 6323 const PetscInt **perms = NULL; 6324 const PetscScalar **flips = NULL; 6325 6326 if (!fieldActive[f]) { 6327 for (p = 0; p < numPoints*2; p += 2) { 6328 PetscInt fdof; 6329 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6330 offset += fdof; 6331 } 6332 continue; 6333 } 6334 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6335 switch (mode) { 6336 case INSERT_VALUES: 6337 for (p = 0; p < numPoints; p++) { 6338 const PetscInt point = points[2*p]; 6339 const PetscInt *perm = perms ? perms[p] : NULL; 6340 const PetscScalar *flip = flips ? flips[p] : NULL; 6341 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6342 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array); 6343 } break; 6344 case INSERT_ALL_VALUES: 6345 for (p = 0; p < numPoints; p++) { 6346 const PetscInt point = points[2*p]; 6347 const PetscInt *perm = perms ? perms[p] : NULL; 6348 const PetscScalar *flip = flips ? flips[p] : NULL; 6349 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6350 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array); 6351 } break; 6352 case INSERT_BC_VALUES: 6353 for (p = 0; p < numPoints; p++) { 6354 const PetscInt point = points[2*p]; 6355 const PetscInt *perm = perms ? perms[p] : NULL; 6356 const PetscScalar *flip = flips ? flips[p] : NULL; 6357 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6358 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array); 6359 } break; 6360 case ADD_VALUES: 6361 for (p = 0; p < numPoints; p++) { 6362 const PetscInt point = points[2*p]; 6363 const PetscInt *perm = perms ? perms[p] : NULL; 6364 const PetscScalar *flip = flips ? flips[p] : NULL; 6365 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6366 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array); 6367 } break; 6368 case ADD_ALL_VALUES: 6369 for (p = 0; p < numPoints; p++) { 6370 const PetscInt point = points[2*p]; 6371 const PetscInt *perm = perms ? perms[p] : NULL; 6372 const PetscScalar *flip = flips ? flips[p] : NULL; 6373 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6374 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array); 6375 } break; 6376 default: 6377 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6378 } 6379 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6380 } 6381 /* Cleanup points */ 6382 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6383 /* Cleanup array */ 6384 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6385 PetscFunctionReturn(0); 6386 } 6387 6388 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6389 { 6390 PetscMPIInt rank; 6391 PetscInt i, j; 6392 PetscErrorCode ierr; 6393 6394 PetscFunctionBegin; 6395 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr); 6396 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 6397 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 6398 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 6399 numCIndices = numCIndices ? numCIndices : numRIndices; 6400 if (!values) PetscFunctionReturn(0); 6401 for (i = 0; i < numRIndices; i++) { 6402 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 6403 for (j = 0; j < numCIndices; j++) { 6404 #if defined(PETSC_USE_COMPLEX) 6405 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 6406 #else 6407 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 6408 #endif 6409 } 6410 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6411 } 6412 PetscFunctionReturn(0); 6413 } 6414 6415 /* 6416 DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 6417 6418 Input Parameters: 6419 + section - The section for this data layout 6420 . islocal - Is the section (and thus indices being requested) local or global? 6421 . point - The point contributing dofs with these indices 6422 . off - The global offset of this point 6423 . loff - The local offset of each field 6424 . setBC - The flag determining whether to include indices of boundary values 6425 . perm - A permutation of the dofs on this point, or NULL 6426 - indperm - A permutation of the entire indices array, or NULL 6427 6428 Output Parameter: 6429 . indices - Indices for dofs on this point 6430 6431 Level: developer 6432 6433 Note: The indices could be local or global, depending on the value of 'off'. 6434 */ 6435 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6436 { 6437 PetscInt dof; /* The number of unknowns on this point */ 6438 PetscInt cdof; /* The number of constraints on this point */ 6439 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6440 PetscInt cind = 0, k; 6441 PetscErrorCode ierr; 6442 6443 PetscFunctionBegin; 6444 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6445 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6446 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6447 if (!cdof || setBC) { 6448 for (k = 0; k < dof; ++k) { 6449 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6450 const PetscInt ind = indperm ? indperm[preind] : preind; 6451 6452 indices[ind] = off + k; 6453 } 6454 } else { 6455 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6456 for (k = 0; k < dof; ++k) { 6457 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6458 const PetscInt ind = indperm ? indperm[preind] : preind; 6459 6460 if ((cind < cdof) && (k == cdofs[cind])) { 6461 /* Insert check for returning constrained indices */ 6462 indices[ind] = -(off+k+1); 6463 ++cind; 6464 } else { 6465 indices[ind] = off + k - (islocal ? 0 : cind); 6466 } 6467 } 6468 } 6469 *loff += dof; 6470 PetscFunctionReturn(0); 6471 } 6472 6473 /* 6474 DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 6475 6476 Input Parameters: 6477 + section - a section (global or local) 6478 - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 6479 . point - point within section 6480 . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 6481 . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 6482 . setBC - identify constrained (boundary condition) points via involution. 6483 . perms - perms[f][permsoff][:] is a permutation of dofs within each field 6484 . permsoff - offset 6485 - indperm - index permutation 6486 6487 Output Parameter: 6488 . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 6489 . indices - array to hold indices (as defined by section) of each dof associated with point 6490 6491 Notes: 6492 If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 6493 If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 6494 in the local vector. 6495 6496 If section is global and setBC=false, the indices for constrained points are negative (and their value is not 6497 significant). It is invalid to call with a global section and setBC=true. 6498 6499 Developer Note: 6500 The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 6501 in the future, global sections may have fields set, in which case we could pass the global section and obtain the 6502 offset could be obtained from the section instead of passing it explicitly as we do now. 6503 6504 Example: 6505 Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 6506 When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 6507 Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 6508 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. 6509 6510 Level: developer 6511 */ 6512 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[]) 6513 { 6514 PetscInt numFields, foff, f; 6515 PetscErrorCode ierr; 6516 6517 PetscFunctionBegin; 6518 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6519 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6520 for (f = 0, foff = 0; f < numFields; ++f) { 6521 PetscInt fdof, cfdof; 6522 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6523 PetscInt cind = 0, b; 6524 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6525 6526 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6527 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6528 if (!cfdof || setBC) { 6529 for (b = 0; b < fdof; ++b) { 6530 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6531 const PetscInt ind = indperm ? indperm[preind] : preind; 6532 6533 indices[ind] = off+foff+b; 6534 } 6535 } else { 6536 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6537 for (b = 0; b < fdof; ++b) { 6538 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6539 const PetscInt ind = indperm ? indperm[preind] : preind; 6540 6541 if ((cind < cfdof) && (b == fcdofs[cind])) { 6542 indices[ind] = -(off+foff+b+1); 6543 ++cind; 6544 } else { 6545 indices[ind] = off + foff + b - (islocal ? 0 : cind); 6546 } 6547 } 6548 } 6549 foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6550 foffs[f] += fdof; 6551 } 6552 PetscFunctionReturn(0); 6553 } 6554 6555 /* 6556 This version believes the globalSection offsets for each field, rather than just the point offset 6557 6558 . foffs - The offset into 'indices' for each field, since it is segregated by field 6559 6560 Notes: 6561 The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6562 Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 6563 */ 6564 static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 6565 { 6566 PetscInt numFields, foff, f; 6567 PetscErrorCode ierr; 6568 6569 PetscFunctionBegin; 6570 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6571 for (f = 0; f < numFields; ++f) { 6572 PetscInt fdof, cfdof; 6573 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6574 PetscInt cind = 0, b; 6575 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6576 6577 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6578 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6579 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 6580 if (!cfdof) { 6581 for (b = 0; b < fdof; ++b) { 6582 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6583 const PetscInt ind = indperm ? indperm[preind] : preind; 6584 6585 indices[ind] = foff+b; 6586 } 6587 } else { 6588 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6589 for (b = 0; b < fdof; ++b) { 6590 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6591 const PetscInt ind = indperm ? indperm[preind] : preind; 6592 6593 if ((cind < cfdof) && (b == fcdofs[cind])) { 6594 indices[ind] = -(foff+b+1); 6595 ++cind; 6596 } else { 6597 indices[ind] = foff+b-cind; 6598 } 6599 } 6600 } 6601 foffs[f] += fdof; 6602 } 6603 PetscFunctionReturn(0); 6604 } 6605 6606 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) 6607 { 6608 Mat cMat; 6609 PetscSection aSec, cSec; 6610 IS aIS; 6611 PetscInt aStart = -1, aEnd = -1; 6612 const PetscInt *anchors; 6613 PetscInt numFields, f, p, q, newP = 0; 6614 PetscInt newNumPoints = 0, newNumIndices = 0; 6615 PetscInt *newPoints, *indices, *newIndices; 6616 PetscInt maxAnchor, maxDof; 6617 PetscInt newOffsets[32]; 6618 PetscInt *pointMatOffsets[32]; 6619 PetscInt *newPointOffsets[32]; 6620 PetscScalar *pointMat[32]; 6621 PetscScalar *newValues=NULL,*tmpValues; 6622 PetscBool anyConstrained = PETSC_FALSE; 6623 PetscErrorCode ierr; 6624 6625 PetscFunctionBegin; 6626 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6627 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6628 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6629 6630 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6631 /* if there are point-to-point constraints */ 6632 if (aSec) { 6633 ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr); 6634 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6635 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 6636 /* figure out how many points are going to be in the new element matrix 6637 * (we allow double counting, because it's all just going to be summed 6638 * into the global matrix anyway) */ 6639 for (p = 0; p < 2*numPoints; p+=2) { 6640 PetscInt b = points[p]; 6641 PetscInt bDof = 0, bSecDof; 6642 6643 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6644 if (!bSecDof) { 6645 continue; 6646 } 6647 if (b >= aStart && b < aEnd) { 6648 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 6649 } 6650 if (bDof) { 6651 /* this point is constrained */ 6652 /* it is going to be replaced by its anchors */ 6653 PetscInt bOff, q; 6654 6655 anyConstrained = PETSC_TRUE; 6656 newNumPoints += bDof; 6657 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 6658 for (q = 0; q < bDof; q++) { 6659 PetscInt a = anchors[bOff + q]; 6660 PetscInt aDof; 6661 6662 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6663 newNumIndices += aDof; 6664 for (f = 0; f < numFields; ++f) { 6665 PetscInt fDof; 6666 6667 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 6668 newOffsets[f+1] += fDof; 6669 } 6670 } 6671 } 6672 else { 6673 /* this point is not constrained */ 6674 newNumPoints++; 6675 newNumIndices += bSecDof; 6676 for (f = 0; f < numFields; ++f) { 6677 PetscInt fDof; 6678 6679 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6680 newOffsets[f+1] += fDof; 6681 } 6682 } 6683 } 6684 } 6685 if (!anyConstrained) { 6686 if (outNumPoints) *outNumPoints = 0; 6687 if (outNumIndices) *outNumIndices = 0; 6688 if (outPoints) *outPoints = NULL; 6689 if (outValues) *outValues = NULL; 6690 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6691 PetscFunctionReturn(0); 6692 } 6693 6694 if (outNumPoints) *outNumPoints = newNumPoints; 6695 if (outNumIndices) *outNumIndices = newNumIndices; 6696 6697 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6698 6699 if (!outPoints && !outValues) { 6700 if (offsets) { 6701 for (f = 0; f <= numFields; f++) { 6702 offsets[f] = newOffsets[f]; 6703 } 6704 } 6705 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6706 PetscFunctionReturn(0); 6707 } 6708 6709 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 6710 6711 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 6712 6713 /* workspaces */ 6714 if (numFields) { 6715 for (f = 0; f < numFields; f++) { 6716 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 6717 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6718 } 6719 } 6720 else { 6721 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 6722 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6723 } 6724 6725 /* get workspaces for the point-to-point matrices */ 6726 if (numFields) { 6727 PetscInt totalOffset, totalMatOffset; 6728 6729 for (p = 0; p < numPoints; p++) { 6730 PetscInt b = points[2*p]; 6731 PetscInt bDof = 0, bSecDof; 6732 6733 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6734 if (!bSecDof) { 6735 for (f = 0; f < numFields; f++) { 6736 newPointOffsets[f][p + 1] = 0; 6737 pointMatOffsets[f][p + 1] = 0; 6738 } 6739 continue; 6740 } 6741 if (b >= aStart && b < aEnd) { 6742 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6743 } 6744 if (bDof) { 6745 for (f = 0; f < numFields; f++) { 6746 PetscInt fDof, q, bOff, allFDof = 0; 6747 6748 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6749 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6750 for (q = 0; q < bDof; q++) { 6751 PetscInt a = anchors[bOff + q]; 6752 PetscInt aFDof; 6753 6754 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 6755 allFDof += aFDof; 6756 } 6757 newPointOffsets[f][p+1] = allFDof; 6758 pointMatOffsets[f][p+1] = fDof * allFDof; 6759 } 6760 } 6761 else { 6762 for (f = 0; f < numFields; f++) { 6763 PetscInt fDof; 6764 6765 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6766 newPointOffsets[f][p+1] = fDof; 6767 pointMatOffsets[f][p+1] = 0; 6768 } 6769 } 6770 } 6771 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 6772 newPointOffsets[f][0] = totalOffset; 6773 pointMatOffsets[f][0] = totalMatOffset; 6774 for (p = 0; p < numPoints; p++) { 6775 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6776 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6777 } 6778 totalOffset = newPointOffsets[f][numPoints]; 6779 totalMatOffset = pointMatOffsets[f][numPoints]; 6780 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 6781 } 6782 } 6783 else { 6784 for (p = 0; p < numPoints; p++) { 6785 PetscInt b = points[2*p]; 6786 PetscInt bDof = 0, bSecDof; 6787 6788 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6789 if (!bSecDof) { 6790 newPointOffsets[0][p + 1] = 0; 6791 pointMatOffsets[0][p + 1] = 0; 6792 continue; 6793 } 6794 if (b >= aStart && b < aEnd) { 6795 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6796 } 6797 if (bDof) { 6798 PetscInt bOff, q, allDof = 0; 6799 6800 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6801 for (q = 0; q < bDof; q++) { 6802 PetscInt a = anchors[bOff + q], aDof; 6803 6804 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 6805 allDof += aDof; 6806 } 6807 newPointOffsets[0][p+1] = allDof; 6808 pointMatOffsets[0][p+1] = bSecDof * allDof; 6809 } 6810 else { 6811 newPointOffsets[0][p+1] = bSecDof; 6812 pointMatOffsets[0][p+1] = 0; 6813 } 6814 } 6815 newPointOffsets[0][0] = 0; 6816 pointMatOffsets[0][0] = 0; 6817 for (p = 0; p < numPoints; p++) { 6818 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6819 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6820 } 6821 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 6822 } 6823 6824 /* output arrays */ 6825 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6826 6827 /* get the point-to-point matrices; construct newPoints */ 6828 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 6829 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6830 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 6831 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 6832 if (numFields) { 6833 for (p = 0, newP = 0; p < numPoints; p++) { 6834 PetscInt b = points[2*p]; 6835 PetscInt o = points[2*p+1]; 6836 PetscInt bDof = 0, bSecDof; 6837 6838 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6839 if (!bSecDof) { 6840 continue; 6841 } 6842 if (b >= aStart && b < aEnd) { 6843 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6844 } 6845 if (bDof) { 6846 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6847 6848 fStart[0] = 0; 6849 fEnd[0] = 0; 6850 for (f = 0; f < numFields; f++) { 6851 PetscInt fDof; 6852 6853 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 6854 fStart[f+1] = fStart[f] + fDof; 6855 fEnd[f+1] = fStart[f+1]; 6856 } 6857 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6858 ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 6859 6860 fAnchorStart[0] = 0; 6861 fAnchorEnd[0] = 0; 6862 for (f = 0; f < numFields; f++) { 6863 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 6864 6865 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 6866 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 6867 } 6868 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6869 for (q = 0; q < bDof; q++) { 6870 PetscInt a = anchors[bOff + q], aOff; 6871 6872 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6873 newPoints[2*(newP + q)] = a; 6874 newPoints[2*(newP + q) + 1] = 0; 6875 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 6876 ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 6877 } 6878 newP += bDof; 6879 6880 if (outValues) { 6881 /* get the point-to-point submatrix */ 6882 for (f = 0; f < numFields; f++) { 6883 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 6884 } 6885 } 6886 } 6887 else { 6888 newPoints[2 * newP] = b; 6889 newPoints[2 * newP + 1] = o; 6890 newP++; 6891 } 6892 } 6893 } else { 6894 for (p = 0; p < numPoints; p++) { 6895 PetscInt b = points[2*p]; 6896 PetscInt o = points[2*p+1]; 6897 PetscInt bDof = 0, bSecDof; 6898 6899 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6900 if (!bSecDof) { 6901 continue; 6902 } 6903 if (b >= aStart && b < aEnd) { 6904 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6905 } 6906 if (bDof) { 6907 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 6908 6909 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6910 ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 6911 6912 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 6913 for (q = 0; q < bDof; q++) { 6914 PetscInt a = anchors[bOff + q], aOff; 6915 6916 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6917 6918 newPoints[2*(newP + q)] = a; 6919 newPoints[2*(newP + q) + 1] = 0; 6920 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 6921 ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 6922 } 6923 newP += bDof; 6924 6925 /* get the point-to-point submatrix */ 6926 if (outValues) { 6927 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 6928 } 6929 } 6930 else { 6931 newPoints[2 * newP] = b; 6932 newPoints[2 * newP + 1] = o; 6933 newP++; 6934 } 6935 } 6936 } 6937 6938 if (outValues) { 6939 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 6940 ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr); 6941 /* multiply constraints on the right */ 6942 if (numFields) { 6943 for (f = 0; f < numFields; f++) { 6944 PetscInt oldOff = offsets[f]; 6945 6946 for (p = 0; p < numPoints; p++) { 6947 PetscInt cStart = newPointOffsets[f][p]; 6948 PetscInt b = points[2 * p]; 6949 PetscInt c, r, k; 6950 PetscInt dof; 6951 6952 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 6953 if (!dof) { 6954 continue; 6955 } 6956 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 6957 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 6958 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 6959 6960 for (r = 0; r < numIndices; r++) { 6961 for (c = 0; c < nCols; c++) { 6962 for (k = 0; k < dof; k++) { 6963 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 6964 } 6965 } 6966 } 6967 } 6968 else { 6969 /* copy this column as is */ 6970 for (r = 0; r < numIndices; r++) { 6971 for (c = 0; c < dof; c++) { 6972 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 6973 } 6974 } 6975 } 6976 oldOff += dof; 6977 } 6978 } 6979 } 6980 else { 6981 PetscInt oldOff = 0; 6982 for (p = 0; p < numPoints; p++) { 6983 PetscInt cStart = newPointOffsets[0][p]; 6984 PetscInt b = points[2 * p]; 6985 PetscInt c, r, k; 6986 PetscInt dof; 6987 6988 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 6989 if (!dof) { 6990 continue; 6991 } 6992 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 6993 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 6994 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 6995 6996 for (r = 0; r < numIndices; r++) { 6997 for (c = 0; c < nCols; c++) { 6998 for (k = 0; k < dof; k++) { 6999 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7000 } 7001 } 7002 } 7003 } 7004 else { 7005 /* copy this column as is */ 7006 for (r = 0; r < numIndices; r++) { 7007 for (c = 0; c < dof; c++) { 7008 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7009 } 7010 } 7011 } 7012 oldOff += dof; 7013 } 7014 } 7015 7016 if (multiplyLeft) { 7017 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 7018 ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr); 7019 /* multiply constraints transpose on the left */ 7020 if (numFields) { 7021 for (f = 0; f < numFields; f++) { 7022 PetscInt oldOff = offsets[f]; 7023 7024 for (p = 0; p < numPoints; p++) { 7025 PetscInt rStart = newPointOffsets[f][p]; 7026 PetscInt b = points[2 * p]; 7027 PetscInt c, r, k; 7028 PetscInt dof; 7029 7030 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7031 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7032 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 7033 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7034 7035 for (r = 0; r < nRows; r++) { 7036 for (c = 0; c < newNumIndices; c++) { 7037 for (k = 0; k < dof; k++) { 7038 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7039 } 7040 } 7041 } 7042 } 7043 else { 7044 /* copy this row as is */ 7045 for (r = 0; r < dof; r++) { 7046 for (c = 0; c < newNumIndices; c++) { 7047 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7048 } 7049 } 7050 } 7051 oldOff += dof; 7052 } 7053 } 7054 } 7055 else { 7056 PetscInt oldOff = 0; 7057 7058 for (p = 0; p < numPoints; p++) { 7059 PetscInt rStart = newPointOffsets[0][p]; 7060 PetscInt b = points[2 * p]; 7061 PetscInt c, r, k; 7062 PetscInt dof; 7063 7064 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7065 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7066 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 7067 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7068 7069 for (r = 0; r < nRows; r++) { 7070 for (c = 0; c < newNumIndices; c++) { 7071 for (k = 0; k < dof; k++) { 7072 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7073 } 7074 } 7075 } 7076 } 7077 else { 7078 /* copy this row as is */ 7079 for (r = 0; r < dof; r++) { 7080 for (c = 0; c < newNumIndices; c++) { 7081 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7082 } 7083 } 7084 } 7085 oldOff += dof; 7086 } 7087 } 7088 7089 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7090 } 7091 else { 7092 newValues = tmpValues; 7093 } 7094 } 7095 7096 /* clean up */ 7097 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 7098 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 7099 7100 if (numFields) { 7101 for (f = 0; f < numFields; f++) { 7102 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 7103 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 7104 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 7105 } 7106 } 7107 else { 7108 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 7109 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 7110 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 7111 } 7112 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7113 7114 /* output */ 7115 if (outPoints) { 7116 *outPoints = newPoints; 7117 } 7118 else { 7119 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 7120 } 7121 if (outValues) { 7122 *outValues = newValues; 7123 } 7124 for (f = 0; f <= numFields; f++) { 7125 offsets[f] = newOffsets[f]; 7126 } 7127 PetscFunctionReturn(0); 7128 } 7129 7130 /*@C 7131 DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 7132 7133 Not collective 7134 7135 Input Parameters: 7136 + dm - The DM 7137 . section - The PetscSection describing the points (a local section) 7138 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7139 . point - The point defining the closure 7140 - useClPerm - Use the closure point permutation if available 7141 7142 Output Parameters: 7143 + numIndices - The number of dof indices in the closure of point with the input sections 7144 . indices - The dof indices 7145 . outOffsets - Array to write the field offsets into, or NULL 7146 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7147 7148 Notes: 7149 Must call DMPlexRestoreClosureIndices() to free allocated memory 7150 7151 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7152 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7153 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7154 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7155 indices (with the above semantics) are implied. 7156 7157 Level: advanced 7158 7159 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7160 @*/ 7161 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7162 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7163 { 7164 /* Closure ordering */ 7165 PetscSection clSection; 7166 IS clPoints; 7167 const PetscInt *clp; 7168 PetscInt *points; 7169 const PetscInt *clperm = NULL; 7170 /* Dof permutation and sign flips */ 7171 const PetscInt **perms[32] = {NULL}; 7172 const PetscScalar **flips[32] = {NULL}; 7173 PetscScalar *valCopy = NULL; 7174 /* Hanging node constraints */ 7175 PetscInt *pointsC = NULL; 7176 PetscScalar *valuesC = NULL; 7177 PetscInt NclC, NiC; 7178 7179 PetscInt *idx; 7180 PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 7181 PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 7182 PetscErrorCode ierr; 7183 7184 PetscFunctionBeginHot; 7185 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7186 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7187 PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7188 if (numIndices) PetscValidPointer(numIndices, 6); 7189 if (indices) PetscValidPointer(indices, 7); 7190 if (outOffsets) PetscValidPointer(outOffsets, 8); 7191 if (values) PetscValidPointer(values, 9); 7192 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 7193 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 7194 ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 7195 /* 1) Get points in closure */ 7196 ierr = DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7197 if (useClPerm) { 7198 PetscInt depth, clsize; 7199 ierr = DMPlexGetPointDepth(dm, point, &depth);CHKERRQ(ierr); 7200 for (clsize=0,p=0; p<Ncl; p++) { 7201 PetscInt dof; 7202 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 7203 clsize += dof; 7204 } 7205 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 7206 } 7207 /* 2) Get number of indices on these points and field offsets from section */ 7208 for (p = 0; p < Ncl*2; p += 2) { 7209 PetscInt dof, fdof; 7210 7211 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7212 for (f = 0; f < Nf; ++f) { 7213 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7214 offsets[f+1] += fdof; 7215 } 7216 Ni += dof; 7217 } 7218 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 7219 if (Nf && offsets[Nf] != Ni) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni); 7220 /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 7221 for (f = 0; f < PetscMax(1, Nf); ++f) { 7222 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7223 else {ierr = PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7224 /* may need to apply sign changes to the element matrix */ 7225 if (values && flips[f]) { 7226 PetscInt foffset = offsets[f]; 7227 7228 for (p = 0; p < Ncl; ++p) { 7229 PetscInt pnt = points[2*p], fdof; 7230 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 7231 7232 if (!Nf) {ierr = PetscSectionGetDof(section, pnt, &fdof);CHKERRQ(ierr);} 7233 else {ierr = PetscSectionGetFieldDof(section, pnt, f, &fdof);CHKERRQ(ierr);} 7234 if (flip) { 7235 PetscInt i, j, k; 7236 7237 if (!valCopy) { 7238 ierr = DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr); 7239 for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 7240 *values = valCopy; 7241 } 7242 for (i = 0; i < fdof; ++i) { 7243 PetscScalar fval = flip[i]; 7244 7245 for (k = 0; k < Ni; ++k) { 7246 valCopy[Ni * (foffset + i) + k] *= fval; 7247 valCopy[Ni * k + (foffset + i)] *= fval; 7248 } 7249 } 7250 } 7251 foffset += fdof; 7252 } 7253 } 7254 } 7255 /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 7256 ierr = DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 7257 if (NclC) { 7258 if (valCopy) {ierr = DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);} 7259 for (f = 0; f < PetscMax(1, Nf); ++f) { 7260 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7261 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7262 } 7263 for (f = 0; f < PetscMax(1, Nf); ++f) { 7264 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7265 else {ierr = PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7266 } 7267 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7268 Ncl = NclC; 7269 Ni = NiC; 7270 points = pointsC; 7271 if (values) *values = valuesC; 7272 } 7273 /* 5) Calculate indices */ 7274 ierr = DMGetWorkArray(dm, Ni, MPIU_INT, &idx);CHKERRQ(ierr); 7275 if (Nf) { 7276 PetscInt idxOff; 7277 PetscBool useFieldOffsets; 7278 7279 if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 7280 ierr = PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets);CHKERRQ(ierr); 7281 if (useFieldOffsets) { 7282 for (p = 0; p < Ncl; ++p) { 7283 const PetscInt pnt = points[p*2]; 7284 7285 ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx);CHKERRQ(ierr); 7286 } 7287 } else { 7288 for (p = 0; p < Ncl; ++p) { 7289 const PetscInt pnt = points[p*2]; 7290 7291 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7292 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7293 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 7294 * global section. */ 7295 ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx);CHKERRQ(ierr); 7296 } 7297 } 7298 } else { 7299 PetscInt off = 0, idxOff; 7300 7301 for (p = 0; p < Ncl; ++p) { 7302 const PetscInt pnt = points[p*2]; 7303 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 7304 7305 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7306 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7307 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 7308 ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx);CHKERRQ(ierr); 7309 } 7310 } 7311 /* 6) Cleanup */ 7312 for (f = 0; f < PetscMax(1, Nf); ++f) { 7313 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7314 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7315 } 7316 if (NclC) { 7317 ierr = DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC);CHKERRQ(ierr); 7318 } else { 7319 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7320 } 7321 7322 if (numIndices) *numIndices = Ni; 7323 if (indices) *indices = idx; 7324 PetscFunctionReturn(0); 7325 } 7326 7327 /*@C 7328 DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 7329 7330 Not collective 7331 7332 Input Parameters: 7333 + dm - The DM 7334 . section - The PetscSection describing the points (a local section) 7335 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7336 . point - The point defining the closure 7337 - useClPerm - Use the closure point permutation if available 7338 7339 Output Parameters: 7340 + numIndices - The number of dof indices in the closure of point with the input sections 7341 . indices - The dof indices 7342 . outOffsets - Array to write the field offsets into, or NULL 7343 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7344 7345 Notes: 7346 If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 7347 7348 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7349 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7350 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7351 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7352 indices (with the above semantics) are implied. 7353 7354 Level: advanced 7355 7356 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7357 @*/ 7358 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7359 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7360 { 7361 PetscErrorCode ierr; 7362 7363 PetscFunctionBegin; 7364 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7365 PetscValidPointer(indices, 7); 7366 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 7367 PetscFunctionReturn(0); 7368 } 7369 7370 /*@C 7371 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 7372 7373 Not collective 7374 7375 Input Parameters: 7376 + dm - The DM 7377 . section - The section describing the layout in v, or NULL to use the default section 7378 . globalSection - The section describing the layout in v, or NULL to use the default global section 7379 . A - The matrix 7380 . point - The point in the DM 7381 . values - The array of values 7382 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7383 7384 Fortran Notes: 7385 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 7386 7387 Level: intermediate 7388 7389 .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7390 @*/ 7391 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7392 { 7393 DM_Plex *mesh = (DM_Plex*) dm->data; 7394 PetscInt *indices; 7395 PetscInt numIndices; 7396 const PetscScalar *valuesOrig = values; 7397 PetscErrorCode ierr; 7398 7399 PetscFunctionBegin; 7400 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7401 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 7402 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7403 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 7404 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 7405 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7406 7407 ierr = DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7408 7409 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 7410 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7411 if (ierr) { 7412 PetscMPIInt rank; 7413 PetscErrorCode ierr2; 7414 7415 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7416 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7417 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 7418 ierr2 = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7419 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7420 CHKERRQ(ierr); 7421 } 7422 if (mesh->printFEM > 1) { 7423 PetscInt i; 7424 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 7425 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 7426 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7427 } 7428 7429 ierr = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7430 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7431 PetscFunctionReturn(0); 7432 } 7433 7434 /*@C 7435 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 7436 7437 Not collective 7438 7439 Input Parameters: 7440 + dmRow - The DM for the row fields 7441 . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 7442 . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 7443 . dmCol - The DM for the column fields 7444 . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 7445 . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 7446 . A - The matrix 7447 . point - The point in the DMs 7448 . values - The array of values 7449 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7450 7451 Level: intermediate 7452 7453 .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7454 @*/ 7455 PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7456 { 7457 DM_Plex *mesh = (DM_Plex*) dmRow->data; 7458 PetscInt *indicesRow, *indicesCol; 7459 PetscInt numIndicesRow, numIndicesCol; 7460 const PetscScalar *valuesOrig = values; 7461 PetscErrorCode ierr; 7462 7463 PetscFunctionBegin; 7464 PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 7465 if (!sectionRow) {ierr = DMGetLocalSection(dmRow, §ionRow);CHKERRQ(ierr);} 7466 PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 7467 if (!globalSectionRow) {ierr = DMGetGlobalSection(dmRow, &globalSectionRow);CHKERRQ(ierr);} 7468 PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 7469 PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 7470 if (!sectionCol) {ierr = DMGetLocalSection(dmCol, §ionCol);CHKERRQ(ierr);} 7471 PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 7472 if (!globalSectionCol) {ierr = DMGetGlobalSection(dmCol, &globalSectionCol);CHKERRQ(ierr);} 7473 PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 7474 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7475 7476 ierr = DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7477 ierr = DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7478 7479 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr);} 7480 ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 7481 if (ierr) { 7482 PetscMPIInt rank; 7483 PetscErrorCode ierr2; 7484 7485 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7486 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7487 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr2); 7488 ierr2 = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7489 ierr2 = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7490 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7491 CHKERRQ(ierr); 7492 } 7493 7494 ierr = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7495 ierr = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7496 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7497 PetscFunctionReturn(0); 7498 } 7499 7500 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7501 { 7502 DM_Plex *mesh = (DM_Plex*) dmf->data; 7503 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7504 PetscInt *cpoints = NULL; 7505 PetscInt *findices, *cindices; 7506 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7507 PetscInt foffsets[32], coffsets[32]; 7508 DMPolytopeType ct; 7509 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7510 PetscErrorCode ierr; 7511 7512 PetscFunctionBegin; 7513 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7514 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7515 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7516 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7517 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7518 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7519 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7520 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7521 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7522 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7523 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7524 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7525 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7526 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7527 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7528 /* Column indices */ 7529 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7530 maxFPoints = numCPoints; 7531 /* Compress out points not in the section */ 7532 /* TODO: Squeeze out points with 0 dof as well */ 7533 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7534 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7535 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7536 cpoints[q*2] = cpoints[p]; 7537 cpoints[q*2+1] = cpoints[p+1]; 7538 ++q; 7539 } 7540 } 7541 numCPoints = q; 7542 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7543 PetscInt fdof; 7544 7545 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7546 if (!dof) continue; 7547 for (f = 0; f < numFields; ++f) { 7548 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7549 coffsets[f+1] += fdof; 7550 } 7551 numCIndices += dof; 7552 } 7553 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7554 /* Row indices */ 7555 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7556 { 7557 DMPlexTransform tr; 7558 DMPolytopeType *rct; 7559 PetscInt *rsize, *rcone, *rornt, Nt; 7560 7561 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7562 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7563 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7564 numSubcells = rsize[Nt-1]; 7565 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7566 } 7567 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7568 for (r = 0, q = 0; r < numSubcells; ++r) { 7569 /* TODO Map from coarse to fine cells */ 7570 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7571 /* Compress out points not in the section */ 7572 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7573 for (p = 0; p < numFPoints*2; p += 2) { 7574 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7575 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7576 if (!dof) continue; 7577 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7578 if (s < q) continue; 7579 ftotpoints[q*2] = fpoints[p]; 7580 ftotpoints[q*2+1] = fpoints[p+1]; 7581 ++q; 7582 } 7583 } 7584 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7585 } 7586 numFPoints = q; 7587 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7588 PetscInt fdof; 7589 7590 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7591 if (!dof) continue; 7592 for (f = 0; f < numFields; ++f) { 7593 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7594 foffsets[f+1] += fdof; 7595 } 7596 numFIndices += dof; 7597 } 7598 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7599 7600 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7601 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7602 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7603 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7604 if (numFields) { 7605 const PetscInt **permsF[32] = {NULL}; 7606 const PetscInt **permsC[32] = {NULL}; 7607 7608 for (f = 0; f < numFields; f++) { 7609 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7610 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7611 } 7612 for (p = 0; p < numFPoints; p++) { 7613 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7614 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7615 } 7616 for (p = 0; p < numCPoints; p++) { 7617 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7618 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7619 } 7620 for (f = 0; f < numFields; f++) { 7621 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7622 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7623 } 7624 } else { 7625 const PetscInt **permsF = NULL; 7626 const PetscInt **permsC = NULL; 7627 7628 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7629 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7630 for (p = 0, off = 0; p < numFPoints; p++) { 7631 const PetscInt *perm = permsF ? permsF[p] : NULL; 7632 7633 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7634 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7635 } 7636 for (p = 0, off = 0; p < numCPoints; p++) { 7637 const PetscInt *perm = permsC ? permsC[p] : NULL; 7638 7639 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7640 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7641 } 7642 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7643 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7644 } 7645 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 7646 /* TODO: flips */ 7647 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7648 if (ierr) { 7649 PetscMPIInt rank; 7650 PetscErrorCode ierr2; 7651 7652 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7653 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7654 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 7655 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 7656 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 7657 CHKERRQ(ierr); 7658 } 7659 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7660 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7661 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7662 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7663 PetscFunctionReturn(0); 7664 } 7665 7666 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 7667 { 7668 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7669 PetscInt *cpoints = NULL; 7670 PetscInt foffsets[32], coffsets[32]; 7671 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7672 DMPolytopeType ct; 7673 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7674 PetscErrorCode ierr; 7675 7676 PetscFunctionBegin; 7677 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7678 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7679 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7680 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7681 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7682 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7683 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7684 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7685 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7686 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7687 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7688 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7689 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7690 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7691 /* Column indices */ 7692 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7693 maxFPoints = numCPoints; 7694 /* Compress out points not in the section */ 7695 /* TODO: Squeeze out points with 0 dof as well */ 7696 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7697 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7698 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7699 cpoints[q*2] = cpoints[p]; 7700 cpoints[q*2+1] = cpoints[p+1]; 7701 ++q; 7702 } 7703 } 7704 numCPoints = q; 7705 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7706 PetscInt fdof; 7707 7708 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7709 if (!dof) continue; 7710 for (f = 0; f < numFields; ++f) { 7711 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7712 coffsets[f+1] += fdof; 7713 } 7714 numCIndices += dof; 7715 } 7716 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7717 /* Row indices */ 7718 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7719 { 7720 DMPlexTransform tr; 7721 DMPolytopeType *rct; 7722 PetscInt *rsize, *rcone, *rornt, Nt; 7723 7724 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7725 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7726 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7727 numSubcells = rsize[Nt-1]; 7728 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7729 } 7730 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7731 for (r = 0, q = 0; r < numSubcells; ++r) { 7732 /* TODO Map from coarse to fine cells */ 7733 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7734 /* Compress out points not in the section */ 7735 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7736 for (p = 0; p < numFPoints*2; p += 2) { 7737 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7738 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7739 if (!dof) continue; 7740 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7741 if (s < q) continue; 7742 ftotpoints[q*2] = fpoints[p]; 7743 ftotpoints[q*2+1] = fpoints[p+1]; 7744 ++q; 7745 } 7746 } 7747 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7748 } 7749 numFPoints = q; 7750 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7751 PetscInt fdof; 7752 7753 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7754 if (!dof) continue; 7755 for (f = 0; f < numFields; ++f) { 7756 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7757 foffsets[f+1] += fdof; 7758 } 7759 numFIndices += dof; 7760 } 7761 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7762 7763 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7764 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7765 if (numFields) { 7766 const PetscInt **permsF[32] = {NULL}; 7767 const PetscInt **permsC[32] = {NULL}; 7768 7769 for (f = 0; f < numFields; f++) { 7770 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7771 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7772 } 7773 for (p = 0; p < numFPoints; p++) { 7774 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7775 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7776 } 7777 for (p = 0; p < numCPoints; p++) { 7778 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7779 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7780 } 7781 for (f = 0; f < numFields; f++) { 7782 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7783 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7784 } 7785 } else { 7786 const PetscInt **permsF = NULL; 7787 const PetscInt **permsC = NULL; 7788 7789 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7790 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7791 for (p = 0, off = 0; p < numFPoints; p++) { 7792 const PetscInt *perm = permsF ? permsF[p] : NULL; 7793 7794 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7795 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7796 } 7797 for (p = 0, off = 0; p < numCPoints; p++) { 7798 const PetscInt *perm = permsC ? permsC[p] : NULL; 7799 7800 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7801 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7802 } 7803 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7804 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7805 } 7806 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7807 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7808 PetscFunctionReturn(0); 7809 } 7810 7811 /*@C 7812 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 7813 7814 Input Parameter: 7815 . dm - The DMPlex object 7816 7817 Output Parameter: 7818 . cellHeight - The height of a cell 7819 7820 Level: developer 7821 7822 .seealso DMPlexSetVTKCellHeight() 7823 @*/ 7824 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7825 { 7826 DM_Plex *mesh = (DM_Plex*) dm->data; 7827 7828 PetscFunctionBegin; 7829 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7830 PetscValidPointer(cellHeight, 2); 7831 *cellHeight = mesh->vtkCellHeight; 7832 PetscFunctionReturn(0); 7833 } 7834 7835 /*@C 7836 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 7837 7838 Input Parameters: 7839 + dm - The DMPlex object 7840 - cellHeight - The height of a cell 7841 7842 Level: developer 7843 7844 .seealso DMPlexGetVTKCellHeight() 7845 @*/ 7846 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7847 { 7848 DM_Plex *mesh = (DM_Plex*) dm->data; 7849 7850 PetscFunctionBegin; 7851 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7852 mesh->vtkCellHeight = cellHeight; 7853 PetscFunctionReturn(0); 7854 } 7855 7856 /*@ 7857 DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 7858 7859 Input Parameter: 7860 . dm - The DMPlex object 7861 7862 Output Parameters: 7863 + gcStart - The first ghost cell, or NULL 7864 - gcEnd - The upper bound on ghost cells, or NULL 7865 7866 Level: advanced 7867 7868 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 7869 @*/ 7870 PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 7871 { 7872 DMLabel ctLabel; 7873 PetscErrorCode ierr; 7874 7875 PetscFunctionBegin; 7876 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7877 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 7878 ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr); 7879 PetscFunctionReturn(0); 7880 } 7881 7882 /* We can easily have a form that takes an IS instead */ 7883 PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 7884 { 7885 PetscSection section, globalSection; 7886 PetscInt *numbers, p; 7887 PetscErrorCode ierr; 7888 7889 PetscFunctionBegin; 7890 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7891 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 7892 for (p = pStart; p < pEnd; ++p) { 7893 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 7894 } 7895 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 7896 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7897 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 7898 for (p = pStart; p < pEnd; ++p) { 7899 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 7900 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 7901 else numbers[p-pStart] += shift; 7902 } 7903 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 7904 if (globalSize) { 7905 PetscLayout layout; 7906 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 7907 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 7908 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 7909 } 7910 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7911 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 7912 PetscFunctionReturn(0); 7913 } 7914 7915 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 7916 { 7917 PetscInt cellHeight, cStart, cEnd; 7918 PetscErrorCode ierr; 7919 7920 PetscFunctionBegin; 7921 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 7922 if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 7923 else {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 7924 ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 7925 PetscFunctionReturn(0); 7926 } 7927 7928 /*@ 7929 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 7930 7931 Input Parameter: 7932 . dm - The DMPlex object 7933 7934 Output Parameter: 7935 . globalCellNumbers - Global cell numbers for all cells on this process 7936 7937 Level: developer 7938 7939 .seealso DMPlexGetVertexNumbering() 7940 @*/ 7941 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 7942 { 7943 DM_Plex *mesh = (DM_Plex*) dm->data; 7944 PetscErrorCode ierr; 7945 7946 PetscFunctionBegin; 7947 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7948 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 7949 *globalCellNumbers = mesh->globalCellNumbers; 7950 PetscFunctionReturn(0); 7951 } 7952 7953 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 7954 { 7955 PetscInt vStart, vEnd; 7956 PetscErrorCode ierr; 7957 7958 PetscFunctionBegin; 7959 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7960 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7961 ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 7962 PetscFunctionReturn(0); 7963 } 7964 7965 /*@ 7966 DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 7967 7968 Input Parameter: 7969 . dm - The DMPlex object 7970 7971 Output Parameter: 7972 . globalVertexNumbers - Global vertex numbers for all vertices on this process 7973 7974 Level: developer 7975 7976 .seealso DMPlexGetCellNumbering() 7977 @*/ 7978 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 7979 { 7980 DM_Plex *mesh = (DM_Plex*) dm->data; 7981 PetscErrorCode ierr; 7982 7983 PetscFunctionBegin; 7984 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7985 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 7986 *globalVertexNumbers = mesh->globalVertexNumbers; 7987 PetscFunctionReturn(0); 7988 } 7989 7990 /*@ 7991 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 7992 7993 Input Parameter: 7994 . dm - The DMPlex object 7995 7996 Output Parameter: 7997 . globalPointNumbers - Global numbers for all points on this process 7998 7999 Level: developer 8000 8001 .seealso DMPlexGetCellNumbering() 8002 @*/ 8003 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8004 { 8005 IS nums[4]; 8006 PetscInt depths[4], gdepths[4], starts[4]; 8007 PetscInt depth, d, shift = 0; 8008 PetscErrorCode ierr; 8009 8010 PetscFunctionBegin; 8011 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8012 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8013 /* For unstratified meshes use dim instead of depth */ 8014 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 8015 for (d = 0; d <= depth; ++d) { 8016 PetscInt end; 8017 8018 depths[d] = depth-d; 8019 ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 8020 if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 8021 } 8022 ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 8023 ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 8024 for (d = 0; d <= depth; ++d) { 8025 if (starts[d] >= 0 && depths[d] != gdepths[d]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 8026 } 8027 for (d = 0; d <= depth; ++d) { 8028 PetscInt pStart, pEnd, gsize; 8029 8030 ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 8031 ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 8032 shift += gsize; 8033 } 8034 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 8035 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 8036 PetscFunctionReturn(0); 8037 } 8038 8039 /*@ 8040 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 8041 8042 Input Parameter: 8043 . dm - The DMPlex object 8044 8045 Output Parameter: 8046 . ranks - The rank field 8047 8048 Options Database Keys: 8049 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 8050 8051 Level: intermediate 8052 8053 .seealso: DMView() 8054 @*/ 8055 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8056 { 8057 DM rdm; 8058 PetscFE fe; 8059 PetscScalar *r; 8060 PetscMPIInt rank; 8061 DMPolytopeType ct; 8062 PetscInt dim, cStart, cEnd, c; 8063 PetscBool simplex; 8064 PetscErrorCode ierr; 8065 8066 PetscFunctionBeginUser; 8067 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8068 PetscValidPointer(ranks, 2); 8069 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 8070 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8071 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8072 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8073 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 8074 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 8075 ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 8076 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 8077 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8078 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8079 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8080 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 8081 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 8082 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 8083 for (c = cStart; c < cEnd; ++c) { 8084 PetscScalar *lr; 8085 8086 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 8087 if (lr) *lr = rank; 8088 } 8089 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 8090 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8091 PetscFunctionReturn(0); 8092 } 8093 8094 /*@ 8095 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 8096 8097 Input Parameters: 8098 + dm - The DMPlex 8099 - label - The DMLabel 8100 8101 Output Parameter: 8102 . val - The label value field 8103 8104 Options Database Keys: 8105 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 8106 8107 Level: intermediate 8108 8109 .seealso: DMView() 8110 @*/ 8111 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8112 { 8113 DM rdm; 8114 PetscFE fe; 8115 PetscScalar *v; 8116 PetscInt dim, cStart, cEnd, c; 8117 PetscErrorCode ierr; 8118 8119 PetscFunctionBeginUser; 8120 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8121 PetscValidPointer(label, 2); 8122 PetscValidPointer(val, 3); 8123 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8124 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8125 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 8126 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 8127 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8128 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8129 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8130 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8131 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 8132 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 8133 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 8134 for (c = cStart; c < cEnd; ++c) { 8135 PetscScalar *lv; 8136 PetscInt cval; 8137 8138 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 8139 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 8140 *lv = cval; 8141 } 8142 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 8143 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8144 PetscFunctionReturn(0); 8145 } 8146 8147 /*@ 8148 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8149 8150 Input Parameter: 8151 . dm - The DMPlex object 8152 8153 Notes: 8154 This is a useful diagnostic when creating meshes programmatically. 8155 8156 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8157 8158 Level: developer 8159 8160 .seealso: DMCreate(), DMSetFromOptions() 8161 @*/ 8162 PetscErrorCode DMPlexCheckSymmetry(DM dm) 8163 { 8164 PetscSection coneSection, supportSection; 8165 const PetscInt *cone, *support; 8166 PetscInt coneSize, c, supportSize, s; 8167 PetscInt pStart, pEnd, p, pp, csize, ssize; 8168 PetscBool storagecheck = PETSC_TRUE; 8169 PetscErrorCode ierr; 8170 8171 PetscFunctionBegin; 8172 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8173 ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr); 8174 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 8175 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 8176 /* Check that point p is found in the support of its cone points, and vice versa */ 8177 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8178 for (p = pStart; p < pEnd; ++p) { 8179 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8180 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8181 for (c = 0; c < coneSize; ++c) { 8182 PetscBool dup = PETSC_FALSE; 8183 PetscInt d; 8184 for (d = c-1; d >= 0; --d) { 8185 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 8186 } 8187 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 8188 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 8189 for (s = 0; s < supportSize; ++s) { 8190 if (support[s] == p) break; 8191 } 8192 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 8193 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 8194 for (s = 0; s < coneSize; ++s) { 8195 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 8196 } 8197 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8198 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 8199 for (s = 0; s < supportSize; ++s) { 8200 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 8201 } 8202 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8203 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 8204 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 8205 } 8206 } 8207 ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 8208 if (p != pp) { storagecheck = PETSC_FALSE; continue; } 8209 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 8210 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 8211 for (s = 0; s < supportSize; ++s) { 8212 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 8213 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 8214 for (c = 0; c < coneSize; ++c) { 8215 ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 8216 if (cone[c] != pp) { c = 0; break; } 8217 if (cone[c] == p) break; 8218 } 8219 if (c >= coneSize) { 8220 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 8221 for (c = 0; c < supportSize; ++c) { 8222 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 8223 } 8224 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8225 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 8226 for (c = 0; c < coneSize; ++c) { 8227 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 8228 } 8229 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8230 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 8231 } 8232 } 8233 } 8234 if (storagecheck) { 8235 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 8236 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 8237 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 8238 } 8239 PetscFunctionReturn(0); 8240 } 8241 8242 /* 8243 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. 8244 */ 8245 static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8246 { 8247 DMPolytopeType cct; 8248 PetscInt ptpoints[4]; 8249 const PetscInt *cone, *ccone, *ptcone; 8250 PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8251 PetscErrorCode ierr; 8252 8253 PetscFunctionBegin; 8254 *unsplit = 0; 8255 switch (ct) { 8256 case DM_POLYTOPE_POINT_PRISM_TENSOR: 8257 ptpoints[npt++] = c; 8258 break; 8259 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8260 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8261 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8262 for (cp = 0; cp < coneSize; ++cp) { 8263 ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr); 8264 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8265 } 8266 break; 8267 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8268 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8269 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8270 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8271 for (cp = 0; cp < coneSize; ++cp) { 8272 ierr = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr); 8273 ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr); 8274 for (ccp = 0; ccp < cconeSize; ++ccp) { 8275 ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr); 8276 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8277 PetscInt p; 8278 for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8279 if (p == npt) ptpoints[npt++] = ccone[ccp]; 8280 } 8281 } 8282 } 8283 break; 8284 default: break; 8285 } 8286 for (pt = 0; pt < npt; ++pt) { 8287 ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr); 8288 if (ptcone[0] == ptcone[1]) ++(*unsplit); 8289 } 8290 PetscFunctionReturn(0); 8291 } 8292 8293 /*@ 8294 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8295 8296 Input Parameters: 8297 + dm - The DMPlex object 8298 - cellHeight - Normally 0 8299 8300 Notes: 8301 This is a useful diagnostic when creating meshes programmatically. 8302 Currently applicable only to homogeneous simplex or tensor meshes. 8303 8304 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8305 8306 Level: developer 8307 8308 .seealso: DMCreate(), DMSetFromOptions() 8309 @*/ 8310 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8311 { 8312 DMPlexInterpolatedFlag interp; 8313 DMPolytopeType ct; 8314 PetscInt vStart, vEnd, cStart, cEnd, c; 8315 PetscErrorCode ierr; 8316 8317 PetscFunctionBegin; 8318 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8319 ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr); 8320 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8321 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8322 for (c = cStart; c < cEnd; ++c) { 8323 PetscInt *closure = NULL; 8324 PetscInt coneSize, closureSize, cl, Nv = 0; 8325 8326 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8327 if ((PetscInt) ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c); 8328 if (ct == DM_POLYTOPE_UNKNOWN) continue; 8329 if (interp == DMPLEX_INTERPOLATED_FULL) { 8330 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8331 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)); 8332 } 8333 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8334 for (cl = 0; cl < closureSize*2; cl += 2) { 8335 const PetscInt p = closure[cl]; 8336 if ((p >= vStart) && (p < vEnd)) ++Nv; 8337 } 8338 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8339 /* Special Case: Tensor faces with identified vertices */ 8340 if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8341 PetscInt unsplit; 8342 8343 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8344 if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 8345 } 8346 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)); 8347 } 8348 PetscFunctionReturn(0); 8349 } 8350 8351 /*@ 8352 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 8353 8354 Not Collective 8355 8356 Input Parameters: 8357 + dm - The DMPlex object 8358 - cellHeight - Normally 0 8359 8360 Notes: 8361 This is a useful diagnostic when creating meshes programmatically. 8362 This routine is only relevant for meshes that are fully interpolated across all ranks. 8363 It will error out if a partially interpolated mesh is given on some rank. 8364 It will do nothing for locally uninterpolated mesh (as there is nothing to check). 8365 8366 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8367 8368 Level: developer 8369 8370 .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 8371 @*/ 8372 PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 8373 { 8374 PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8375 PetscErrorCode ierr; 8376 DMPlexInterpolatedFlag interpEnum; 8377 8378 PetscFunctionBegin; 8379 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8380 ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr); 8381 if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 8382 if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 8383 PetscMPIInt rank; 8384 MPI_Comm comm; 8385 8386 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8387 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8388 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 8389 } 8390 8391 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8392 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8393 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8394 for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 8395 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 8396 for (c = cStart; c < cEnd; ++c) { 8397 const PetscInt *cone, *ornt, *faceSizes, *faces; 8398 const DMPolytopeType *faceTypes; 8399 DMPolytopeType ct; 8400 PetscInt numFaces, coneSize, f; 8401 PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 8402 8403 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8404 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8405 if (unsplit) continue; 8406 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8407 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8408 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 8409 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8410 for (cl = 0; cl < closureSize*2; cl += 2) { 8411 const PetscInt p = closure[cl]; 8412 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 8413 } 8414 ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8415 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); 8416 for (f = 0; f < numFaces; ++f) { 8417 DMPolytopeType fct; 8418 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 8419 8420 ierr = DMPlexGetCellType(dm, cone[f], &fct);CHKERRQ(ierr); 8421 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8422 for (cl = 0; cl < fclosureSize*2; cl += 2) { 8423 const PetscInt p = fclosure[cl]; 8424 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 8425 } 8426 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]); 8427 for (v = 0; v < fnumCorners; ++v) { 8428 if (fclosure[v] != faces[fOff+v]) { 8429 PetscInt v1; 8430 8431 ierr = PetscPrintf(PETSC_COMM_SELF, "face closure:");CHKERRQ(ierr); 8432 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", fclosure[v1]);CHKERRQ(ierr);} 8433 ierr = PetscPrintf(PETSC_COMM_SELF, "\ncell face:");CHKERRQ(ierr); 8434 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", faces[fOff+v1]);CHKERRQ(ierr);} 8435 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8436 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]); 8437 } 8438 } 8439 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8440 fOff += faceSizes[f]; 8441 } 8442 ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8443 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8444 } 8445 } 8446 PetscFunctionReturn(0); 8447 } 8448 8449 /*@ 8450 DMPlexCheckGeometry - Check the geometry of mesh cells 8451 8452 Input Parameter: 8453 . dm - The DMPlex object 8454 8455 Notes: 8456 This is a useful diagnostic when creating meshes programmatically. 8457 8458 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8459 8460 Level: developer 8461 8462 .seealso: DMCreate(), DMSetFromOptions() 8463 @*/ 8464 PetscErrorCode DMPlexCheckGeometry(DM dm) 8465 { 8466 Vec coordinates; 8467 PetscReal detJ, J[9], refVol = 1.0; 8468 PetscReal vol; 8469 PetscBool periodic; 8470 PetscInt dim, depth, dE, d, cStart, cEnd, c; 8471 PetscErrorCode ierr; 8472 8473 PetscFunctionBegin; 8474 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8475 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 8476 if (dim != dE) PetscFunctionReturn(0); 8477 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8478 ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr); 8479 for (d = 0; d < dim; ++d) refVol *= 2.0; 8480 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8481 /* Make sure local coordinates are created, because that step is collective */ 8482 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8483 for (c = cStart; c < cEnd; ++c) { 8484 DMPolytopeType ct; 8485 PetscInt unsplit; 8486 PetscBool ignoreZeroVol = PETSC_FALSE; 8487 8488 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8489 switch (ct) { 8490 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8491 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8492 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8493 ignoreZeroVol = PETSC_TRUE; break; 8494 default: break; 8495 } 8496 switch (ct) { 8497 case DM_POLYTOPE_TRI_PRISM: 8498 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8499 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8500 case DM_POLYTOPE_PYRAMID: 8501 continue; 8502 default: break; 8503 } 8504 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8505 if (unsplit) continue; 8506 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 8507 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); 8508 ierr = PetscInfo2(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 8509 if (depth > 1 && !periodic) { 8510 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 8511 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); 8512 ierr = PetscInfo2(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 8513 } 8514 } 8515 PetscFunctionReturn(0); 8516 } 8517 8518 /*@ 8519 DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 8520 8521 Input Parameters: 8522 . dm - The DMPlex object 8523 8524 Notes: 8525 This is mainly intended for debugging/testing purposes. 8526 It currently checks only meshes with no partition overlapping. 8527 8528 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8529 8530 Level: developer 8531 8532 .seealso: DMGetPointSF(), DMSetFromOptions() 8533 @*/ 8534 PetscErrorCode DMPlexCheckPointSF(DM dm) 8535 { 8536 PetscSF pointSF; 8537 PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 8538 const PetscInt *locals, *rootdegree; 8539 PetscBool distributed; 8540 PetscErrorCode ierr; 8541 8542 PetscFunctionBegin; 8543 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8544 ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr); 8545 ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 8546 if (!distributed) PetscFunctionReturn(0); 8547 ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 8548 if (overlap) { 8549 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping");CHKERRQ(ierr); 8550 PetscFunctionReturn(0); 8551 } 8552 if (!pointSF) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 8553 ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr); 8554 if (nroots < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 8555 ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 8556 ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 8557 8558 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 8559 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8560 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8561 for (l = 0; l < nleaves; ++l) { 8562 const PetscInt point = locals[l]; 8563 8564 if (point >= cStart && point < cEnd) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 8565 } 8566 8567 /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 8568 for (l = 0; l < nleaves; ++l) { 8569 const PetscInt point = locals[l]; 8570 const PetscInt *cone; 8571 PetscInt coneSize, c, idx; 8572 8573 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 8574 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 8575 for (c = 0; c < coneSize; ++c) { 8576 if (!rootdegree[cone[c]]) { 8577 ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr); 8578 if (idx < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 8579 } 8580 } 8581 } 8582 PetscFunctionReturn(0); 8583 } 8584 8585 PetscErrorCode DMPlexCheckAll_Internal(DM dm, PetscInt cellHeight) 8586 { 8587 PetscErrorCode ierr; 8588 8589 PetscFunctionBegin; 8590 ierr = DMPlexCheckSymmetry(dm);CHKERRQ(ierr); 8591 ierr = DMPlexCheckSkeleton(dm, cellHeight);CHKERRQ(ierr); 8592 ierr = DMPlexCheckFaces(dm, cellHeight);CHKERRQ(ierr); 8593 ierr = DMPlexCheckGeometry(dm);CHKERRQ(ierr); 8594 ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr); 8595 ierr = DMPlexCheckInterfaceCones(dm);CHKERRQ(ierr); 8596 PetscFunctionReturn(0); 8597 } 8598 8599 typedef struct cell_stats 8600 { 8601 PetscReal min, max, sum, squaresum; 8602 PetscInt count; 8603 } cell_stats_t; 8604 8605 static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8606 { 8607 PetscInt i, N = *len; 8608 8609 for (i = 0; i < N; i++) { 8610 cell_stats_t *A = (cell_stats_t *) a; 8611 cell_stats_t *B = (cell_stats_t *) b; 8612 8613 B->min = PetscMin(A->min,B->min); 8614 B->max = PetscMax(A->max,B->max); 8615 B->sum += A->sum; 8616 B->squaresum += A->squaresum; 8617 B->count += A->count; 8618 } 8619 } 8620 8621 /*@ 8622 DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8623 8624 Collective on dm 8625 8626 Input Parameters: 8627 + dm - The DMPlex object 8628 . output - If true, statistics will be displayed on stdout 8629 - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8630 8631 Notes: 8632 This is mainly intended for debugging/testing purposes. 8633 8634 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8635 8636 Level: developer 8637 8638 .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality() 8639 @*/ 8640 PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8641 { 8642 DM dmCoarse; 8643 cell_stats_t stats, globalStats; 8644 MPI_Comm comm = PetscObjectComm((PetscObject)dm); 8645 PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 8646 PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8647 PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 8648 PetscMPIInt rank,size; 8649 PetscErrorCode ierr; 8650 8651 PetscFunctionBegin; 8652 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8653 stats.min = PETSC_MAX_REAL; 8654 stats.max = PETSC_MIN_REAL; 8655 stats.sum = stats.squaresum = 0.; 8656 stats.count = 0; 8657 8658 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 8659 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8660 ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr); 8661 ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr); 8662 ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 8663 ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); 8664 for (c = cStart; c < cEnd; c++) { 8665 PetscInt i; 8666 PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8667 8668 ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 8669 if (detJ < 0.0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 8670 for (i = 0; i < PetscSqr(cdim); ++i) { 8671 frobJ += J[i] * J[i]; 8672 frobInvJ += invJ[i] * invJ[i]; 8673 } 8674 cond2 = frobJ * frobInvJ; 8675 cond = PetscSqrtReal(cond2); 8676 8677 stats.min = PetscMin(stats.min,cond); 8678 stats.max = PetscMax(stats.max,cond); 8679 stats.sum += cond; 8680 stats.squaresum += cond2; 8681 stats.count++; 8682 if (output && cond > limit) { 8683 PetscSection coordSection; 8684 Vec coordsLocal; 8685 PetscScalar *coords = NULL; 8686 PetscInt Nv, d, clSize, cl, *closure = NULL; 8687 8688 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8689 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8690 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8691 ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr); 8692 for (i = 0; i < Nv/cdim; ++i) { 8693 ierr = PetscSynchronizedPrintf(comm, " Vertex %D: (", i);CHKERRQ(ierr); 8694 for (d = 0; d < cdim; ++d) { 8695 if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);} 8696 ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr); 8697 } 8698 ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr); 8699 } 8700 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8701 for (cl = 0; cl < clSize*2; cl += 2) { 8702 const PetscInt edge = closure[cl]; 8703 8704 if ((edge >= eStart) && (edge < eEnd)) { 8705 PetscReal len; 8706 8707 ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr); 8708 ierr = PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr); 8709 } 8710 } 8711 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8712 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8713 } 8714 } 8715 if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 8716 8717 if (size > 1) { 8718 PetscMPIInt blockLengths[2] = {4,1}; 8719 MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8720 MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8721 MPI_Op statReduce; 8722 8723 ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRMPI(ierr); 8724 ierr = MPI_Type_commit(&statType);CHKERRMPI(ierr); 8725 ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRMPI(ierr); 8726 ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRMPI(ierr); 8727 ierr = MPI_Op_free(&statReduce);CHKERRMPI(ierr); 8728 ierr = MPI_Type_free(&statType);CHKERRMPI(ierr); 8729 } else { 8730 ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr); 8731 } 8732 if (rank == 0) { 8733 count = globalStats.count; 8734 min = globalStats.min; 8735 max = globalStats.max; 8736 mean = globalStats.sum / globalStats.count; 8737 stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8738 } 8739 8740 if (output) { 8741 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); 8742 } 8743 ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 8744 8745 ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 8746 if (dmCoarse) { 8747 PetscBool isplex; 8748 8749 ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 8750 if (isplex) { 8751 ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr); 8752 } 8753 } 8754 PetscFunctionReturn(0); 8755 } 8756 8757 /*@ 8758 DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8759 orthogonal quality below given tolerance. 8760 8761 Collective on dm 8762 8763 Input Parameters: 8764 + dm - The DMPlex object 8765 . fv - Optional PetscFV object for pre-computed cell/face centroid information 8766 - atol - [0, 1] Absolute tolerance for tagging cells. 8767 8768 Output Parameters: 8769 + OrthQual - Vec containing orthogonal quality per cell 8770 - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8771 8772 Options Database Keys: 8773 + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8774 supported. 8775 - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8776 8777 Notes: 8778 Orthogonal quality is given by the following formula: 8779 8780 \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8781 8782 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 8783 is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8784 current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8785 calculating the cosine of the angle between these vectors. 8786 8787 Orthogonal quality ranges from 1 (best) to 0 (worst). 8788 8789 This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8790 pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8791 8792 Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8793 8794 Level: intermediate 8795 8796 .seealso: DMPlexCheckCellShape(), DMCreateLabel() 8797 @*/ 8798 PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8799 { 8800 PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 8801 PetscInt *idx; 8802 PetscScalar *oqVals; 8803 const PetscScalar *cellGeomArr, *faceGeomArr; 8804 PetscReal *ci, *fi, *Ai; 8805 MPI_Comm comm; 8806 Vec cellgeom, facegeom; 8807 DM dmFace, dmCell; 8808 IS glob; 8809 ISLocalToGlobalMapping ltog; 8810 PetscViewer vwr; 8811 PetscErrorCode ierr; 8812 8813 PetscFunctionBegin; 8814 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8815 if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8816 PetscValidPointer(OrthQual, 4); 8817 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); 8818 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8819 ierr = DMGetDimension(dm, &nc);CHKERRQ(ierr); 8820 if (nc < 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc); 8821 { 8822 DMPlexInterpolatedFlag interpFlag; 8823 8824 ierr = DMPlexIsInterpolated(dm, &interpFlag);CHKERRQ(ierr); 8825 if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 8826 PetscMPIInt rank; 8827 8828 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8829 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 8830 } 8831 } 8832 if (OrthQualLabel) { 8833 PetscValidPointer(OrthQualLabel, 5); 8834 ierr = DMCreateLabel(dm, "Orthogonal_Quality");CHKERRQ(ierr); 8835 ierr = DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel);CHKERRQ(ierr); 8836 } else {*OrthQualLabel = NULL;} 8837 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8838 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8839 ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob);CHKERRQ(ierr); 8840 ierr = ISLocalToGlobalMappingCreateIS(glob, <og);CHKERRQ(ierr); 8841 ierr = ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 8842 ierr = VecCreate(comm, OrthQual);CHKERRQ(ierr); 8843 ierr = VecSetType(*OrthQual, VECSTANDARD);CHKERRQ(ierr); 8844 ierr = VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr); 8845 ierr = VecSetLocalToGlobalMapping(*OrthQual, ltog);CHKERRQ(ierr); 8846 ierr = VecSetUp(*OrthQual);CHKERRQ(ierr); 8847 ierr = ISDestroy(&glob);CHKERRQ(ierr); 8848 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 8849 ierr = DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL);CHKERRQ(ierr); 8850 ierr = VecGetArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8851 ierr = VecGetArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8852 ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr); 8853 ierr = VecGetDM(facegeom, &dmFace);CHKERRQ(ierr); 8854 ierr = PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai);CHKERRQ(ierr); 8855 for (cell = cStart; cell < cEnd; cellIter++,cell++) { 8856 PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 8857 PetscInt cellarr[2], *adj = NULL; 8858 PetscScalar *cArr, *fArr; 8859 PetscReal minvalc = 1.0, minvalf = 1.0; 8860 PetscFVCellGeom *cg; 8861 8862 idx[cellIter] = cell-cStart; 8863 cellarr[0] = cell; 8864 /* Make indexing into cellGeom easier */ 8865 ierr = DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg);CHKERRQ(ierr); 8866 ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj);CHKERRQ(ierr); 8867 /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 8868 ierr = PetscCalloc2(adjSize, &cArr, adjSize, &fArr);CHKERRQ(ierr); 8869 for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 8870 PetscInt i; 8871 const PetscInt neigh = adj[cellneigh]; 8872 PetscReal normci = 0, normfi = 0, normai = 0; 8873 PetscFVCellGeom *cgneigh; 8874 PetscFVFaceGeom *fg; 8875 8876 /* Don't count ourselves in the neighbor list */ 8877 if (neigh == cell) continue; 8878 ierr = DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh);CHKERRQ(ierr); 8879 cellarr[1] = neigh; 8880 { 8881 PetscInt numcovpts; 8882 const PetscInt *covpts; 8883 8884 ierr = DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 8885 ierr = DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg);CHKERRQ(ierr); 8886 ierr = DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 8887 } 8888 8889 /* Compute c_i, f_i and their norms */ 8890 for (i = 0; i < nc; i++) { 8891 ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 8892 fi[i] = fg->centroid[i] - cg->centroid[i]; 8893 Ai[i] = fg->normal[i]; 8894 normci += PetscPowReal(ci[i], 2); 8895 normfi += PetscPowReal(fi[i], 2); 8896 normai += PetscPowReal(Ai[i], 2); 8897 } 8898 normci = PetscSqrtReal(normci); 8899 normfi = PetscSqrtReal(normfi); 8900 normai = PetscSqrtReal(normai); 8901 8902 /* Normalize and compute for each face-cell-normal pair */ 8903 for (i = 0; i < nc; i++) { 8904 ci[i] = ci[i]/normci; 8905 fi[i] = fi[i]/normfi; 8906 Ai[i] = Ai[i]/normai; 8907 /* PetscAbs because I don't know if normals are guaranteed to point out */ 8908 cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 8909 fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 8910 } 8911 if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 8912 minvalc = PetscRealPart(cArr[cellneighiter]); 8913 } 8914 if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 8915 minvalf = PetscRealPart(fArr[cellneighiter]); 8916 } 8917 } 8918 ierr = PetscFree(adj);CHKERRQ(ierr); 8919 ierr = PetscFree2(cArr, fArr);CHKERRQ(ierr); 8920 /* Defer to cell if they're equal */ 8921 oqVals[cellIter] = PetscMin(minvalf, minvalc); 8922 if (OrthQualLabel) { 8923 if (PetscRealPart(oqVals[cellIter]) <= atol) {ierr = DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE);CHKERRQ(ierr);} 8924 } 8925 } 8926 ierr = VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES);CHKERRQ(ierr); 8927 ierr = VecAssemblyBegin(*OrthQual);CHKERRQ(ierr); 8928 ierr = VecAssemblyEnd(*OrthQual);CHKERRQ(ierr); 8929 ierr = VecRestoreArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8930 ierr = VecRestoreArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8931 ierr = PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL);CHKERRQ(ierr); 8932 if (OrthQualLabel) { 8933 if (vwr) {ierr = DMLabelView(*OrthQualLabel, vwr);CHKERRQ(ierr);} 8934 } 8935 ierr = PetscFree5(idx, oqVals, ci, fi, Ai);CHKERRQ(ierr); 8936 ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr); 8937 ierr = VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view");CHKERRQ(ierr); 8938 PetscFunctionReturn(0); 8939 } 8940 8941 /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 8942 * interpolator construction */ 8943 static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 8944 { 8945 PetscSection section, newSection, gsection; 8946 PetscSF sf; 8947 PetscBool hasConstraints, ghasConstraints; 8948 PetscErrorCode ierr; 8949 8950 PetscFunctionBegin; 8951 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8952 PetscValidPointer(odm,2); 8953 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 8954 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 8955 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 8956 if (!ghasConstraints) { 8957 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 8958 *odm = dm; 8959 PetscFunctionReturn(0); 8960 } 8961 ierr = DMClone(dm, odm);CHKERRQ(ierr); 8962 ierr = DMCopyFields(dm, *odm);CHKERRQ(ierr); 8963 ierr = DMGetLocalSection(*odm, &newSection);CHKERRQ(ierr); 8964 ierr = DMGetPointSF(*odm, &sf);CHKERRQ(ierr); 8965 ierr = PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 8966 ierr = DMSetGlobalSection(*odm, gsection);CHKERRQ(ierr); 8967 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 8968 PetscFunctionReturn(0); 8969 } 8970 8971 static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 8972 { 8973 DM dmco, dmfo; 8974 Mat interpo; 8975 Vec rscale; 8976 Vec cglobalo, clocal; 8977 Vec fglobal, fglobalo, flocal; 8978 PetscBool regular; 8979 PetscErrorCode ierr; 8980 8981 PetscFunctionBegin; 8982 ierr = DMGetFullDM(dmc, &dmco);CHKERRQ(ierr); 8983 ierr = DMGetFullDM(dmf, &dmfo);CHKERRQ(ierr); 8984 ierr = DMSetCoarseDM(dmfo, dmco);CHKERRQ(ierr); 8985 ierr = DMPlexGetRegularRefinement(dmf, ®ular);CHKERRQ(ierr); 8986 ierr = DMPlexSetRegularRefinement(dmfo, regular);CHKERRQ(ierr); 8987 ierr = DMCreateInterpolation(dmco, dmfo, &interpo, &rscale);CHKERRQ(ierr); 8988 ierr = DMCreateGlobalVector(dmco, &cglobalo);CHKERRQ(ierr); 8989 ierr = DMCreateLocalVector(dmc, &clocal);CHKERRQ(ierr); 8990 ierr = VecSet(cglobalo, 0.);CHKERRQ(ierr); 8991 ierr = VecSet(clocal, 0.);CHKERRQ(ierr); 8992 ierr = DMCreateGlobalVector(dmf, &fglobal);CHKERRQ(ierr); 8993 ierr = DMCreateGlobalVector(dmfo, &fglobalo);CHKERRQ(ierr); 8994 ierr = DMCreateLocalVector(dmf, &flocal);CHKERRQ(ierr); 8995 ierr = VecSet(fglobal, 0.);CHKERRQ(ierr); 8996 ierr = VecSet(fglobalo, 0.);CHKERRQ(ierr); 8997 ierr = VecSet(flocal, 0.);CHKERRQ(ierr); 8998 ierr = DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL);CHKERRQ(ierr); 8999 ierr = DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9000 ierr = DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9001 ierr = MatMult(interpo, cglobalo, fglobalo);CHKERRQ(ierr); 9002 ierr = DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9003 ierr = DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9004 ierr = DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9005 ierr = DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9006 *shift = fglobal; 9007 ierr = VecDestroy(&flocal);CHKERRQ(ierr); 9008 ierr = VecDestroy(&fglobalo);CHKERRQ(ierr); 9009 ierr = VecDestroy(&clocal);CHKERRQ(ierr); 9010 ierr = VecDestroy(&cglobalo);CHKERRQ(ierr); 9011 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9012 ierr = MatDestroy(&interpo);CHKERRQ(ierr); 9013 ierr = DMDestroy(&dmfo);CHKERRQ(ierr); 9014 ierr = DMDestroy(&dmco);CHKERRQ(ierr); 9015 PetscFunctionReturn(0); 9016 } 9017 9018 PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9019 { 9020 PetscObject shifto; 9021 Vec shift; 9022 9023 PetscErrorCode ierr; 9024 9025 PetscFunctionBegin; 9026 if (!interp) { 9027 Vec rscale; 9028 9029 ierr = DMCreateInterpolation(coarse, fine, &interp, &rscale);CHKERRQ(ierr); 9030 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9031 } else { 9032 ierr = PetscObjectReference((PetscObject)interp);CHKERRQ(ierr); 9033 } 9034 ierr = PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto);CHKERRQ(ierr); 9035 if (!shifto) { 9036 ierr = DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift);CHKERRQ(ierr); 9037 ierr = PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift);CHKERRQ(ierr); 9038 shifto = (PetscObject) shift; 9039 ierr = VecDestroy(&shift);CHKERRQ(ierr); 9040 } 9041 shift = (Vec) shifto; 9042 ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr); 9043 ierr = VecAXPY(fineSol, 1.0, shift);CHKERRQ(ierr); 9044 ierr = MatDestroy(&interp);CHKERRQ(ierr); 9045 PetscFunctionReturn(0); 9046 } 9047 9048 /* Pointwise interpolation 9049 Just code FEM for now 9050 u^f = I u^c 9051 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 9052 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 9053 I_{ij} = psi^f_i phi^c_j 9054 */ 9055 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9056 { 9057 PetscSection gsc, gsf; 9058 PetscInt m, n; 9059 void *ctx; 9060 DM cdm; 9061 PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9062 PetscErrorCode ierr; 9063 9064 PetscFunctionBegin; 9065 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9066 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9067 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9068 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9069 9070 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 9071 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 9072 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9073 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 9074 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9075 9076 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9077 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9078 if (!isRefined || (regular && cdm == dmCoarse)) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx);CHKERRQ(ierr);} 9079 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 9080 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 9081 if (scaling) { 9082 /* Use naive scaling */ 9083 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 9084 } 9085 PetscFunctionReturn(0); 9086 } 9087 9088 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9089 { 9090 PetscErrorCode ierr; 9091 VecScatter ctx; 9092 9093 PetscFunctionBegin; 9094 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 9095 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 9096 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 9097 PetscFunctionReturn(0); 9098 } 9099 9100 static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9101 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9102 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9103 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 9104 { 9105 g0[0] = 1.0; 9106 } 9107 9108 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9109 { 9110 PetscSection gsc, gsf; 9111 PetscInt m, n; 9112 void *ctx; 9113 DM cdm; 9114 PetscBool regular; 9115 PetscErrorCode ierr; 9116 9117 PetscFunctionBegin; 9118 if (dmFine == dmCoarse) { 9119 DM dmc; 9120 PetscDS ds; 9121 Vec u; 9122 IS cellIS; 9123 PetscFormKey key; 9124 PetscInt depth; 9125 9126 ierr = DMClone(dmFine, &dmc);CHKERRQ(ierr); 9127 ierr = DMCopyDisc(dmFine, dmc);CHKERRQ(ierr); 9128 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9129 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9130 ierr = DMCreateMatrix(dmc, mass);CHKERRQ(ierr); 9131 ierr = DMGetGlobalVector(dmc, &u);CHKERRQ(ierr); 9132 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9133 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9134 ierr = MatZeroEntries(*mass);CHKERRQ(ierr); 9135 key.label = NULL; 9136 key.value = 0; 9137 key.field = 0; 9138 key.part = 0; 9139 ierr = DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL);CHKERRQ(ierr); 9140 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9141 ierr = DMRestoreGlobalVector(dmc, &u);CHKERRQ(ierr); 9142 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9143 } else { 9144 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9145 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9146 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9147 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9148 9149 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 9150 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9151 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 9152 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9153 9154 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9155 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9156 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9157 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9158 } 9159 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 9160 PetscFunctionReturn(0); 9161 } 9162 9163 /*@ 9164 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9165 9166 Input Parameter: 9167 . dm - The DMPlex object 9168 9169 Output Parameter: 9170 . regular - The flag 9171 9172 Level: intermediate 9173 9174 .seealso: DMPlexSetRegularRefinement() 9175 @*/ 9176 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 9177 { 9178 PetscFunctionBegin; 9179 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9180 PetscValidPointer(regular, 2); 9181 *regular = ((DM_Plex *) dm->data)->regularRefinement; 9182 PetscFunctionReturn(0); 9183 } 9184 9185 /*@ 9186 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9187 9188 Input Parameters: 9189 + dm - The DMPlex object 9190 - regular - The flag 9191 9192 Level: intermediate 9193 9194 .seealso: DMPlexGetRegularRefinement() 9195 @*/ 9196 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 9197 { 9198 PetscFunctionBegin; 9199 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9200 ((DM_Plex *) dm->data)->regularRefinement = regular; 9201 PetscFunctionReturn(0); 9202 } 9203 9204 /* anchors */ 9205 /*@ 9206 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9207 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 9208 9209 not collective 9210 9211 Input Parameter: 9212 . dm - The DMPlex object 9213 9214 Output Parameters: 9215 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9216 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9217 9218 Level: intermediate 9219 9220 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 9221 @*/ 9222 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9223 { 9224 DM_Plex *plex = (DM_Plex *)dm->data; 9225 PetscErrorCode ierr; 9226 9227 PetscFunctionBegin; 9228 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9229 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 9230 if (anchorSection) *anchorSection = plex->anchorSection; 9231 if (anchorIS) *anchorIS = plex->anchorIS; 9232 PetscFunctionReturn(0); 9233 } 9234 9235 /*@ 9236 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9237 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9238 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9239 9240 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9241 DMGetConstraints() and filling in the entries in the constraint matrix. 9242 9243 collective on dm 9244 9245 Input Parameters: 9246 + dm - The DMPlex object 9247 . 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). 9248 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9249 9250 The reference counts of anchorSection and anchorIS are incremented. 9251 9252 Level: intermediate 9253 9254 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 9255 @*/ 9256 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9257 { 9258 DM_Plex *plex = (DM_Plex *)dm->data; 9259 PetscMPIInt result; 9260 PetscErrorCode ierr; 9261 9262 PetscFunctionBegin; 9263 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9264 if (anchorSection) { 9265 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 9266 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRMPI(ierr); 9267 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9268 } 9269 if (anchorIS) { 9270 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 9271 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRMPI(ierr); 9272 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9273 } 9274 9275 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 9276 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 9277 plex->anchorSection = anchorSection; 9278 9279 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 9280 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 9281 plex->anchorIS = anchorIS; 9282 9283 if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9284 PetscInt size, a, pStart, pEnd; 9285 const PetscInt *anchors; 9286 9287 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9288 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 9289 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 9290 for (a = 0; a < size; a++) { 9291 PetscInt p; 9292 9293 p = anchors[a]; 9294 if (p >= pStart && p < pEnd) { 9295 PetscInt dof; 9296 9297 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9298 if (dof) { 9299 PetscErrorCode ierr2; 9300 9301 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 9302 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 9303 } 9304 } 9305 } 9306 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 9307 } 9308 /* reset the generic constraints */ 9309 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 9310 PetscFunctionReturn(0); 9311 } 9312 9313 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9314 { 9315 PetscSection anchorSection; 9316 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9317 PetscErrorCode ierr; 9318 9319 PetscFunctionBegin; 9320 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9321 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9322 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 9323 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9324 if (numFields) { 9325 PetscInt f; 9326 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 9327 9328 for (f = 0; f < numFields; f++) { 9329 PetscInt numComp; 9330 9331 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 9332 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 9333 } 9334 } 9335 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9336 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9337 pStart = PetscMax(pStart,sStart); 9338 pEnd = PetscMin(pEnd,sEnd); 9339 pEnd = PetscMax(pStart,pEnd); 9340 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 9341 for (p = pStart; p < pEnd; p++) { 9342 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9343 if (dof) { 9344 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 9345 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 9346 for (f = 0; f < numFields; f++) { 9347 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 9348 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 9349 } 9350 } 9351 } 9352 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 9353 ierr = PetscObjectSetName((PetscObject) *cSec, "Constraint Section");CHKERRQ(ierr); 9354 PetscFunctionReturn(0); 9355 } 9356 9357 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9358 { 9359 PetscSection aSec; 9360 PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 9361 const PetscInt *anchors; 9362 PetscInt numFields, f; 9363 IS aIS; 9364 PetscErrorCode ierr; 9365 MatType mtype; 9366 PetscBool iscuda,iskokkos; 9367 9368 PetscFunctionBegin; 9369 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9370 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 9371 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 9372 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 9373 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 9374 ierr = PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr); 9375 if (!iscuda) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr); } 9376 ierr = PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos);CHKERRQ(ierr); 9377 if (!iskokkos) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos);CHKERRQ(ierr); } 9378 if (iscuda) mtype = MATSEQAIJCUSPARSE; 9379 else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9380 else mtype = MATSEQAIJ; 9381 ierr = MatSetType(*cMat,mtype);CHKERRQ(ierr); 9382 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 9383 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 9384 /* cSec will be a subset of aSec and section */ 9385 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 9386 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9387 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 9388 i[0] = 0; 9389 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9390 for (p = pStart; p < pEnd; p++) { 9391 PetscInt rDof, rOff, r; 9392 9393 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9394 if (!rDof) continue; 9395 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9396 if (numFields) { 9397 for (f = 0; f < numFields; f++) { 9398 annz = 0; 9399 for (r = 0; r < rDof; r++) { 9400 a = anchors[rOff + r]; 9401 if (a < sStart || a >= sEnd) continue; 9402 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9403 annz += aDof; 9404 } 9405 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9406 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 9407 for (q = 0; q < dof; q++) { 9408 i[off + q + 1] = i[off + q] + annz; 9409 } 9410 } 9411 } 9412 else { 9413 annz = 0; 9414 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9415 for (q = 0; q < dof; q++) { 9416 a = anchors[rOff + q]; 9417 if (a < sStart || a >= sEnd) continue; 9418 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9419 annz += aDof; 9420 } 9421 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9422 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 9423 for (q = 0; q < dof; q++) { 9424 i[off + q + 1] = i[off + q] + annz; 9425 } 9426 } 9427 } 9428 nnz = i[m]; 9429 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 9430 offset = 0; 9431 for (p = pStart; p < pEnd; p++) { 9432 if (numFields) { 9433 for (f = 0; f < numFields; f++) { 9434 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9435 for (q = 0; q < dof; q++) { 9436 PetscInt rDof, rOff, r; 9437 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9438 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9439 for (r = 0; r < rDof; r++) { 9440 PetscInt s; 9441 9442 a = anchors[rOff + r]; 9443 if (a < sStart || a >= sEnd) continue; 9444 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9445 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 9446 for (s = 0; s < aDof; s++) { 9447 j[offset++] = aOff + s; 9448 } 9449 } 9450 } 9451 } 9452 } 9453 else { 9454 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9455 for (q = 0; q < dof; q++) { 9456 PetscInt rDof, rOff, r; 9457 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9458 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9459 for (r = 0; r < rDof; r++) { 9460 PetscInt s; 9461 9462 a = anchors[rOff + r]; 9463 if (a < sStart || a >= sEnd) continue; 9464 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9465 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 9466 for (s = 0; s < aDof; s++) { 9467 j[offset++] = aOff + s; 9468 } 9469 } 9470 } 9471 } 9472 } 9473 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 9474 ierr = PetscFree(i);CHKERRQ(ierr); 9475 ierr = PetscFree(j);CHKERRQ(ierr); 9476 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 9477 PetscFunctionReturn(0); 9478 } 9479 9480 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 9481 { 9482 DM_Plex *plex = (DM_Plex *)dm->data; 9483 PetscSection anchorSection, section, cSec; 9484 Mat cMat; 9485 PetscErrorCode ierr; 9486 9487 PetscFunctionBegin; 9488 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9489 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9490 if (anchorSection) { 9491 PetscInt Nf; 9492 9493 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 9494 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 9495 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 9496 ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 9497 if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 9498 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 9499 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 9500 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 9501 } 9502 PetscFunctionReturn(0); 9503 } 9504 9505 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9506 { 9507 IS subis; 9508 PetscSection section, subsection; 9509 PetscErrorCode ierr; 9510 9511 PetscFunctionBegin; 9512 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9513 if (!section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 9514 if (!subdm) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9515 /* Create subdomain */ 9516 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 9517 /* Create submodel */ 9518 ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr); 9519 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 9520 ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr); 9521 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 9522 ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 9523 /* Create map from submodel to global model */ 9524 if (is) { 9525 PetscSection sectionGlobal, subsectionGlobal; 9526 IS spIS; 9527 const PetscInt *spmap; 9528 PetscInt *subIndices; 9529 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9530 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9531 9532 ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 9533 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 9534 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 9535 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 9536 ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 9537 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 9538 for (p = pStart; p < pEnd; ++p) { 9539 PetscInt gdof, pSubSize = 0; 9540 9541 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 9542 if (gdof > 0) { 9543 for (f = 0; f < Nf; ++f) { 9544 PetscInt fdof, fcdof; 9545 9546 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 9547 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 9548 pSubSize += fdof-fcdof; 9549 } 9550 subSize += pSubSize; 9551 if (pSubSize) { 9552 if (bs < 0) { 9553 bs = pSubSize; 9554 } else if (bs != pSubSize) { 9555 /* Layout does not admit a pointwise block size */ 9556 bs = 1; 9557 } 9558 } 9559 } 9560 } 9561 /* Must have same blocksize on all procs (some might have no points) */ 9562 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 9563 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 9564 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9565 else {bs = bsMinMax[0];} 9566 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 9567 for (p = pStart; p < pEnd; ++p) { 9568 PetscInt gdof, goff; 9569 9570 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 9571 if (gdof > 0) { 9572 const PetscInt point = spmap[p]; 9573 9574 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 9575 for (f = 0; f < Nf; ++f) { 9576 PetscInt fdof, fcdof, fc, f2, poff = 0; 9577 9578 /* Can get rid of this loop by storing field information in the global section */ 9579 for (f2 = 0; f2 < f; ++f2) { 9580 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 9581 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 9582 poff += fdof-fcdof; 9583 } 9584 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 9585 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 9586 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9587 subIndices[subOff] = goff+poff+fc; 9588 } 9589 } 9590 } 9591 } 9592 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 9593 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 9594 if (bs > 1) { 9595 /* We need to check that the block size does not come from non-contiguous fields */ 9596 PetscInt i, j, set = 1; 9597 for (i = 0; i < subSize; i += bs) { 9598 for (j = 0; j < bs; ++j) { 9599 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9600 } 9601 } 9602 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 9603 } 9604 /* Attach nullspace */ 9605 for (f = 0; f < Nf; ++f) { 9606 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9607 if ((*subdm)->nullspaceConstructors[f]) break; 9608 } 9609 if (f < Nf) { 9610 MatNullSpace nullSpace; 9611 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace);CHKERRQ(ierr); 9612 9613 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 9614 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 9615 } 9616 } 9617 PetscFunctionReturn(0); 9618 } 9619 9620 /*@ 9621 DMPlexMonitorThroughput - Report the cell throughput of FE integration 9622 9623 Input Parameter: 9624 - dm - The DM 9625 9626 Level: developer 9627 9628 Options Database Keys: 9629 . -dm_plex_monitor_throughput - Activate the monitor 9630 9631 .seealso: DMSetFromOptions(), DMPlexCreate() 9632 @*/ 9633 PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9634 { 9635 #if defined(PETSC_USE_LOG) 9636 PetscStageLog stageLog; 9637 PetscLogEvent event; 9638 PetscLogStage stage; 9639 PetscEventPerfInfo eventInfo; 9640 PetscReal cellRate, flopRate; 9641 PetscInt cStart, cEnd, Nf, N; 9642 const char *name; 9643 PetscErrorCode ierr; 9644 #endif 9645 9646 PetscFunctionBegin; 9647 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9648 #if defined(PETSC_USE_LOG) 9649 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 9650 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9651 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9652 ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 9653 ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr); 9654 ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr); 9655 ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr); 9656 N = (cEnd - cStart)*Nf*eventInfo.count; 9657 flopRate = eventInfo.flops/eventInfo.time; 9658 cellRate = N/eventInfo.time; 9659 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); 9660 #else 9661 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9662 #endif 9663 PetscFunctionReturn(0); 9664 } 9665