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