1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petsc/private/isimpl.h> 3 #include <petsc/private/vecimpl.h> 4 #include <petsc/private/glvisvecimpl.h> 5 #include <petscsf.h> 6 #include <petscds.h> 7 #include <petscdraw.h> 8 #include <petscdmfield.h> 9 #include <petscdmplextransform.h> 10 11 /* Logging support */ 12 PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF,DMPLEX_LocatePoints; 13 14 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 15 16 /*@ 17 DMPlexIsSimplex - Is the first cell in this mesh a simplex? 18 19 Input Parameter: 20 . dm - The DMPlex object 21 22 Output Parameter: 23 . simplex - Flag checking for a simplex 24 25 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 26 If the mesh has no cells, this returns PETSC_FALSE. 27 28 Level: intermediate 29 30 .seealso DMPlexGetSimplexOrBoxCells(), DMPlexGetCellType(), DMPlexGetHeightStratum(), DMPolytopeTypeGetNumVertices() 31 @*/ 32 PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 33 { 34 DMPolytopeType ct; 35 PetscInt cStart, cEnd; 36 PetscErrorCode ierr; 37 38 PetscFunctionBegin; 39 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 40 if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);} 41 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 42 *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 43 PetscFunctionReturn(0); 44 } 45 46 /*@ 47 DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 48 49 Input Parameters: 50 + dm - The DMPlex object 51 - height - The cell height in the Plex, 0 is the default 52 53 Output Parameters: 54 + cStart - The first "normal" cell 55 - cEnd - The upper bound on "normal"" cells 56 57 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 58 59 Level: developer 60 61 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 62 @*/ 63 PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 64 { 65 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 66 PetscInt cS, cE, c; 67 PetscErrorCode ierr; 68 69 PetscFunctionBegin; 70 ierr = DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE);CHKERRQ(ierr); 71 for (c = cS; c < cE; ++c) { 72 DMPolytopeType cct; 73 74 ierr = DMPlexGetCellType(dm, c, &cct);CHKERRQ(ierr); 75 if ((PetscInt) cct < 0) break; 76 switch (cct) { 77 case DM_POLYTOPE_POINT: 78 case DM_POLYTOPE_SEGMENT: 79 case DM_POLYTOPE_TRIANGLE: 80 case DM_POLYTOPE_QUADRILATERAL: 81 case DM_POLYTOPE_TETRAHEDRON: 82 case DM_POLYTOPE_HEXAHEDRON: 83 ct = cct; 84 break; 85 default: break; 86 } 87 if (ct != DM_POLYTOPE_UNKNOWN) break; 88 } 89 if (ct != DM_POLYTOPE_UNKNOWN) { 90 DMLabel ctLabel; 91 92 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 93 ierr = DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE);CHKERRQ(ierr); 94 } 95 if (cStart) *cStart = cS; 96 if (cEnd) *cEnd = cE; 97 PetscFunctionReturn(0); 98 } 99 100 PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 101 { 102 PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 103 PetscInt vcdof[2] = {0,0}, globalvcdof[2]; 104 PetscErrorCode ierr; 105 106 PetscFunctionBegin; 107 *ft = PETSC_VTK_INVALID; 108 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 109 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 110 ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 111 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 112 if (field >= 0) { 113 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]);CHKERRQ(ierr);} 114 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]);CHKERRQ(ierr);} 115 } else { 116 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vcdof[0]);CHKERRQ(ierr);} 117 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &vcdof[1]);CHKERRQ(ierr);} 118 } 119 ierr = MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 120 if (globalvcdof[0]) { 121 *sStart = vStart; 122 *sEnd = vEnd; 123 if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 124 else *ft = PETSC_VTK_POINT_FIELD; 125 } else if (globalvcdof[1]) { 126 *sStart = cStart; 127 *sEnd = cEnd; 128 if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 129 else *ft = PETSC_VTK_CELL_FIELD; 130 } else { 131 if (field >= 0) { 132 const char *fieldname; 133 134 ierr = PetscSectionGetFieldName(section, field, &fieldname);CHKERRQ(ierr); 135 ierr = PetscInfo2((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname);CHKERRQ(ierr); 136 } else { 137 ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\"%s\"\n");CHKERRQ(ierr); 138 } 139 } 140 PetscFunctionReturn(0); 141 } 142 143 static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 144 { 145 DM dm; 146 PetscSection s; 147 PetscDraw draw, popup; 148 DM cdm; 149 PetscSection coordSection; 150 Vec coordinates; 151 const PetscScalar *coords, *array; 152 PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 153 PetscReal vbound[2], time; 154 PetscBool isnull, flg; 155 PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 156 const char *name; 157 char title[PETSC_MAX_PATH_LEN]; 158 PetscErrorCode ierr; 159 160 PetscFunctionBegin; 161 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 162 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 163 if (isnull) PetscFunctionReturn(0); 164 165 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 166 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 167 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D. Use PETSCVIEWERGLVIS", dim); 168 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 169 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 170 ierr = DMGetCoarsenLevel(dm, &level);CHKERRQ(ierr); 171 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 172 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 173 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 174 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 175 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 176 177 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 178 ierr = DMGetOutputSequenceNumber(dm, &step, &time);CHKERRQ(ierr); 179 180 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 181 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 182 for (c = 0; c < N; c += dim) { 183 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 184 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 185 } 186 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 187 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 188 189 /* Could implement something like DMDASelectFields() */ 190 for (f = 0; f < Nf; ++f) { 191 DM fdm = dm; 192 Vec fv = v; 193 IS fis; 194 char prefix[PETSC_MAX_PATH_LEN]; 195 const char *fname; 196 197 ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr); 198 ierr = PetscSectionGetFieldName(s, f, &fname);CHKERRQ(ierr); 199 200 if (v->hdr.prefix) {ierr = PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix));CHKERRQ(ierr);} 201 else {prefix[0] = '\0';} 202 if (Nf > 1) { 203 ierr = DMCreateSubDM(dm, 1, &f, &fis, &fdm);CHKERRQ(ierr); 204 ierr = VecGetSubVector(v, fis, &fv);CHKERRQ(ierr); 205 ierr = PetscStrlcat(prefix, fname,sizeof(prefix));CHKERRQ(ierr); 206 ierr = PetscStrlcat(prefix, "_",sizeof(prefix));CHKERRQ(ierr); 207 } 208 for (comp = 0; comp < Nc; ++comp, ++w) { 209 PetscInt nmax = 2; 210 211 ierr = PetscViewerDrawGetDraw(viewer, w, &draw);CHKERRQ(ierr); 212 if (Nc > 1) {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time);CHKERRQ(ierr);} 213 else {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time);CHKERRQ(ierr);} 214 ierr = PetscDrawSetTitle(draw, title);CHKERRQ(ierr); 215 216 /* TODO Get max and min only for this component */ 217 ierr = PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg);CHKERRQ(ierr); 218 if (!flg) { 219 ierr = VecMin(fv, NULL, &vbound[0]);CHKERRQ(ierr); 220 ierr = VecMax(fv, NULL, &vbound[1]);CHKERRQ(ierr); 221 if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 222 } 223 ierr = PetscDrawGetPopup(draw, &popup);CHKERRQ(ierr); 224 ierr = PetscDrawScalePopup(popup, vbound[0], vbound[1]);CHKERRQ(ierr); 225 ierr = PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]);CHKERRQ(ierr); 226 227 ierr = VecGetArrayRead(fv, &array);CHKERRQ(ierr); 228 for (c = cStart; c < cEnd; ++c) { 229 PetscScalar *coords = NULL, *a = NULL; 230 PetscInt numCoords, color[4] = {-1,-1,-1,-1}; 231 232 ierr = DMPlexPointLocalRead(fdm, c, array, &a);CHKERRQ(ierr); 233 if (a) { 234 color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 235 color[1] = color[2] = color[3] = color[0]; 236 } else { 237 PetscScalar *vals = NULL; 238 PetscInt numVals, va; 239 240 ierr = DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 241 if (numVals % Nc) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %D does not divide the number of values in the closure %D", Nc, numVals); 242 switch (numVals/Nc) { 243 case 3: /* P1 Triangle */ 244 case 4: /* P1 Quadrangle */ 245 for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]); 246 break; 247 case 6: /* P2 Triangle */ 248 case 8: /* P2 Quadrangle */ 249 for (va = 0; va < numVals/(Nc*2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp + numVals/(Nc*2)]), vbound[0], vbound[1]); 250 break; 251 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc); 252 } 253 ierr = DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 254 } 255 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 256 switch (numCoords) { 257 case 6: 258 case 12: /* Localized triangle */ 259 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 260 break; 261 case 8: 262 case 16: /* Localized quadrilateral */ 263 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 264 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0]);CHKERRQ(ierr); 265 break; 266 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords); 267 } 268 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 269 } 270 ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr); 271 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 272 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 273 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 274 } 275 if (Nf > 1) { 276 ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr); 277 ierr = ISDestroy(&fis);CHKERRQ(ierr); 278 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 279 } 280 } 281 PetscFunctionReturn(0); 282 } 283 284 static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 285 { 286 DM dm; 287 Vec locv; 288 const char *name; 289 PetscSection section; 290 PetscInt pStart, pEnd; 291 PetscInt numFields; 292 PetscViewerVTKFieldType ft; 293 PetscErrorCode ierr; 294 295 PetscFunctionBegin; 296 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 297 ierr = DMCreateLocalVector(dm, &locv);CHKERRQ(ierr); /* VTK viewer requires exclusive ownership of the vector */ 298 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 299 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 300 ierr = VecCopy(v, locv);CHKERRQ(ierr); 301 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 302 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 303 if (!numFields) { 304 ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 305 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 306 } else { 307 PetscInt f; 308 309 for (f = 0; f < numFields; f++) { 310 ierr = DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft);CHKERRQ(ierr); 311 if (ft == PETSC_VTK_INVALID) continue; 312 ierr = PetscObjectReference((PetscObject)locv);CHKERRQ(ierr); 313 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 314 } 315 ierr = VecDestroy(&locv);CHKERRQ(ierr); 316 } 317 PetscFunctionReturn(0); 318 } 319 320 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 321 { 322 DM dm; 323 PetscBool isvtk, ishdf5, isdraw, isglvis; 324 PetscErrorCode ierr; 325 326 PetscFunctionBegin; 327 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 328 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 329 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 330 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 331 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 332 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 333 if (isvtk || ishdf5 || isdraw || isglvis) { 334 PetscInt i,numFields; 335 PetscObject fe; 336 PetscBool fem = PETSC_FALSE; 337 Vec locv = v; 338 const char *name; 339 PetscInt step; 340 PetscReal time; 341 342 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 343 for (i=0; i<numFields; i++) { 344 ierr = DMGetField(dm, i, NULL, &fe);CHKERRQ(ierr); 345 if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; } 346 } 347 if (fem) { 348 PetscObject isZero; 349 350 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 351 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 352 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 353 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 354 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 355 ierr = VecCopy(v, locv);CHKERRQ(ierr); 356 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 357 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr); 358 } 359 if (isvtk) { 360 ierr = VecView_Plex_Local_VTK(locv, viewer);CHKERRQ(ierr); 361 } else if (ishdf5) { 362 #if defined(PETSC_HAVE_HDF5) 363 ierr = VecView_Plex_Local_HDF5_Internal(locv, viewer);CHKERRQ(ierr); 364 #else 365 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 366 #endif 367 } else if (isdraw) { 368 ierr = VecView_Plex_Local_Draw(locv, viewer);CHKERRQ(ierr); 369 } else if (isglvis) { 370 ierr = DMGetOutputSequenceNumber(dm, &step, NULL);CHKERRQ(ierr); 371 ierr = PetscViewerGLVisSetSnapId(viewer, step);CHKERRQ(ierr); 372 ierr = VecView_GLVis(locv, viewer);CHKERRQ(ierr); 373 } 374 if (fem) { 375 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 376 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 377 } 378 } else { 379 PetscBool isseq; 380 381 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 382 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 383 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 384 } 385 PetscFunctionReturn(0); 386 } 387 388 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 389 { 390 DM dm; 391 PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii; 392 PetscErrorCode ierr; 393 394 PetscFunctionBegin; 395 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 396 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 397 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 398 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 399 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 400 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 401 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 402 if (isvtk || isdraw || isglvis) { 403 Vec locv; 404 PetscObject isZero; 405 const char *name; 406 407 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 408 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 409 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 410 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 411 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 412 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 413 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 414 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 415 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 416 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 417 } else if (ishdf5) { 418 #if defined(PETSC_HAVE_HDF5) 419 ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 420 #else 421 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 422 #endif 423 } else if (isexodusii) { 424 #if defined(PETSC_HAVE_EXODUSII) 425 ierr = VecView_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 426 #else 427 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 428 #endif 429 } else { 430 PetscBool isseq; 431 432 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 433 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 434 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 435 } 436 PetscFunctionReturn(0); 437 } 438 439 PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 440 { 441 DM dm; 442 MPI_Comm comm; 443 PetscViewerFormat format; 444 Vec v; 445 PetscBool isvtk, ishdf5; 446 PetscErrorCode ierr; 447 448 PetscFunctionBegin; 449 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 450 ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 451 if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 452 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 453 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 454 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 455 if (format == PETSC_VIEWER_NATIVE) { 456 /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 457 /* this need a better fix */ 458 if (dm->useNatural) { 459 if (dm->sfNatural) { 460 const char *vecname; 461 PetscInt n, nroots; 462 463 ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr); 464 ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 465 if (n == nroots) { 466 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 467 ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 468 ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 469 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 470 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 471 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 472 } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 473 } else v = originalv; 474 } else v = originalv; 475 476 if (ishdf5) { 477 #if defined(PETSC_HAVE_HDF5) 478 ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 479 #else 480 SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 481 #endif 482 } else if (isvtk) { 483 SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 484 } else { 485 PetscBool isseq; 486 487 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 488 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 489 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 490 } 491 if (v != originalv) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 492 PetscFunctionReturn(0); 493 } 494 495 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 496 { 497 DM dm; 498 PetscBool ishdf5; 499 PetscErrorCode ierr; 500 501 PetscFunctionBegin; 502 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 503 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 504 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 505 if (ishdf5) { 506 DM dmBC; 507 Vec gv; 508 const char *name; 509 510 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 511 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 512 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 513 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 514 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 515 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 516 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 517 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 518 } else { 519 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 520 } 521 PetscFunctionReturn(0); 522 } 523 524 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 525 { 526 DM dm; 527 PetscBool ishdf5,isexodusii; 528 PetscErrorCode ierr; 529 530 PetscFunctionBegin; 531 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 532 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 533 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 534 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 535 if (ishdf5) { 536 #if defined(PETSC_HAVE_HDF5) 537 ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 538 #else 539 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 540 #endif 541 } else if (isexodusii) { 542 #if defined(PETSC_HAVE_EXODUSII) 543 ierr = VecLoad_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 544 #else 545 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 546 #endif 547 } else { 548 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 549 } 550 PetscFunctionReturn(0); 551 } 552 553 PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 554 { 555 DM dm; 556 PetscViewerFormat format; 557 PetscBool ishdf5; 558 PetscErrorCode ierr; 559 560 PetscFunctionBegin; 561 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 562 if (!dm) SETERRQ(PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 563 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 564 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 565 if (format == PETSC_VIEWER_NATIVE) { 566 if (dm->useNatural) { 567 if (dm->sfNatural) { 568 if (ishdf5) { 569 #if defined(PETSC_HAVE_HDF5) 570 Vec v; 571 const char *vecname; 572 573 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 574 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 575 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 576 ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 577 ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 578 ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 579 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 580 #else 581 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 582 #endif 583 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 584 } 585 } else { 586 ierr = VecLoad_Default(originalv, viewer);CHKERRQ(ierr); 587 } 588 } 589 PetscFunctionReturn(0); 590 } 591 592 PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 593 { 594 PetscSection coordSection; 595 Vec coordinates; 596 DMLabel depthLabel, celltypeLabel; 597 const char *name[4]; 598 const PetscScalar *a; 599 PetscInt dim, pStart, pEnd, cStart, cEnd, c; 600 PetscErrorCode ierr; 601 602 PetscFunctionBegin; 603 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 604 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 605 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 606 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 607 ierr = DMPlexGetCellTypeLabel(dm, &celltypeLabel);CHKERRQ(ierr); 608 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 609 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 610 ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 611 name[0] = "vertex"; 612 name[1] = "edge"; 613 name[dim-1] = "face"; 614 name[dim] = "cell"; 615 for (c = cStart; c < cEnd; ++c) { 616 PetscInt *closure = NULL; 617 PetscInt closureSize, cl, ct; 618 619 ierr = DMLabelGetValue(celltypeLabel, c, &ct);CHKERRQ(ierr); 620 ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]);CHKERRQ(ierr); 621 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 622 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 623 for (cl = 0; cl < closureSize*2; cl += 2) { 624 PetscInt point = closure[cl], depth, dof, off, d, p; 625 626 if ((point < pStart) || (point >= pEnd)) continue; 627 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 628 if (!dof) continue; 629 ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 630 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 631 ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr); 632 for (p = 0; p < dof/dim; ++p) { 633 ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 634 for (d = 0; d < dim; ++d) { 635 if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 636 ierr = PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 637 } 638 ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 639 } 640 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 641 } 642 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 643 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 644 } 645 ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 646 PetscFunctionReturn(0); 647 } 648 649 typedef enum {CS_CARTESIAN, CS_POLAR, CS_CYLINDRICAL, CS_SPHERICAL} CoordSystem; 650 const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 651 652 static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 653 { 654 PetscInt i; 655 PetscErrorCode ierr; 656 657 PetscFunctionBegin; 658 if (dim > 3) { 659 for (i = 0; i < dim; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) PetscRealPart(x[i]));CHKERRQ(ierr);} 660 } else { 661 PetscReal coords[3], trcoords[3]; 662 663 for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 664 switch (cs) { 665 case CS_CARTESIAN: for (i = 0; i < dim; ++i) trcoords[i] = coords[i];break; 666 case CS_POLAR: 667 if (dim != 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %D", dim); 668 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 669 trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 670 break; 671 case CS_CYLINDRICAL: 672 if (dim != 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %D", dim); 673 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 674 trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 675 trcoords[2] = coords[2]; 676 break; 677 case CS_SPHERICAL: 678 if (dim != 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %D", dim); 679 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 680 trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 681 trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 682 break; 683 } 684 for (i = 0; i < dim; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) trcoords[i]);CHKERRQ(ierr);} 685 } 686 PetscFunctionReturn(0); 687 } 688 689 static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 690 { 691 DM_Plex *mesh = (DM_Plex*) dm->data; 692 DM cdm; 693 PetscSection coordSection; 694 Vec coordinates; 695 PetscViewerFormat format; 696 PetscErrorCode ierr; 697 698 PetscFunctionBegin; 699 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 700 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 701 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 702 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 703 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 704 const char *name; 705 PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 706 PetscInt pStart, pEnd, p, numLabels, l; 707 PetscMPIInt rank, size; 708 709 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 710 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 711 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 712 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 713 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 714 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 715 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 716 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 717 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 718 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 719 ierr = PetscViewerASCIIPrintf(viewer, "Supports:\n", name);CHKERRQ(ierr); 720 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 721 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize);CHKERRQ(ierr); 722 for (p = pStart; p < pEnd; ++p) { 723 PetscInt dof, off, s; 724 725 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 726 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 727 for (s = off; s < off+dof; ++s) { 728 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 729 } 730 } 731 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 732 ierr = PetscViewerASCIIPrintf(viewer, "Cones:\n", name);CHKERRQ(ierr); 733 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize);CHKERRQ(ierr); 734 for (p = pStart; p < pEnd; ++p) { 735 PetscInt dof, off, c; 736 737 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 738 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 739 for (c = off; c < off+dof; ++c) { 740 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 741 } 742 } 743 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 744 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 745 if (coordSection && coordinates) { 746 CoordSystem cs = CS_CARTESIAN; 747 const PetscScalar *array; 748 PetscInt Nf, Nc, pStart, pEnd, p; 749 PetscMPIInt rank; 750 const char *name; 751 752 ierr = PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL);CHKERRQ(ierr); 753 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRMPI(ierr); 754 ierr = PetscSectionGetNumFields(coordSection, &Nf);CHKERRQ(ierr); 755 if (Nf != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %D", Nf); 756 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 757 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 758 ierr = PetscObjectGetName((PetscObject) coordinates, &name);CHKERRQ(ierr); 759 ierr = PetscViewerASCIIPrintf(viewer, "%s with %D fields\n", name, Nf);CHKERRQ(ierr); 760 ierr = PetscViewerASCIIPrintf(viewer, " field 0 with %D components\n", Nc);CHKERRQ(ierr); 761 if (cs != CS_CARTESIAN) {ierr = PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs]);CHKERRQ(ierr);} 762 763 ierr = VecGetArrayRead(coordinates, &array);CHKERRQ(ierr); 764 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 765 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank);CHKERRQ(ierr); 766 for (p = pStart; p < pEnd; ++p) { 767 PetscInt dof, off; 768 769 ierr = PetscSectionGetDof(coordSection, p, &dof);CHKERRQ(ierr); 770 ierr = PetscSectionGetOffset(coordSection, p, &off);CHKERRQ(ierr); 771 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " (%4D) dim %2D offset %3D", p, dof, off);CHKERRQ(ierr); 772 ierr = DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]);CHKERRQ(ierr); 773 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\n");CHKERRQ(ierr); 774 } 775 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 776 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 777 ierr = VecRestoreArrayRead(coordinates, &array);CHKERRQ(ierr); 778 } 779 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 780 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 781 for (l = 0; l < numLabels; ++l) { 782 DMLabel label; 783 PetscBool isdepth; 784 const char *name; 785 786 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 787 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 788 if (isdepth) continue; 789 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 790 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 791 } 792 if (size > 1) { 793 PetscSF sf; 794 795 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 796 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 797 } 798 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 799 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 800 const char *name, *color; 801 const char *defcolors[3] = {"gray", "orange", "green"}; 802 const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 803 char lname[PETSC_MAX_PATH_LEN]; 804 PetscReal scale = 2.0; 805 PetscReal tikzscale = 1.0; 806 PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 807 double tcoords[3]; 808 PetscScalar *coords; 809 PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 810 PetscMPIInt rank, size; 811 char **names, **colors, **lcolors; 812 PetscBool flg, lflg; 813 PetscBT wp = NULL; 814 PetscInt pEnd, pStart; 815 816 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 817 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 818 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 819 numLabels = PetscMax(numLabels, 10); 820 numColors = 10; 821 numLColors = 10; 822 ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 823 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 824 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL);CHKERRQ(ierr); 825 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 826 for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 827 for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 828 n = 4; 829 ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg);CHKERRQ(ierr); 830 if (flg && n != dim+1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 831 ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg);CHKERRQ(ierr); 832 if (flg && n != dim+1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 833 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 834 if (!useLabels) numLabels = 0; 835 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 836 if (!useColors) { 837 numColors = 3; 838 for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 839 } 840 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 841 if (!useColors) { 842 numLColors = 4; 843 for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 844 } 845 ierr = PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg);CHKERRQ(ierr); 846 plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 847 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg);CHKERRQ(ierr); 848 if (flg && plotEdges && depth < dim) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 849 if (depth < dim) plotEdges = PETSC_FALSE; 850 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL);CHKERRQ(ierr); 851 852 /* filter points with labelvalue != labeldefaultvalue */ 853 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 854 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 855 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 856 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 857 if (lflg) { 858 DMLabel lbl; 859 860 ierr = DMGetLabel(dm, lname, &lbl);CHKERRQ(ierr); 861 if (lbl) { 862 PetscInt val, defval; 863 864 ierr = DMLabelGetDefaultValue(lbl, &defval);CHKERRQ(ierr); 865 ierr = PetscBTCreate(pEnd-pStart, &wp);CHKERRQ(ierr); 866 for (c = pStart; c < pEnd; c++) { 867 PetscInt *closure = NULL; 868 PetscInt closureSize; 869 870 ierr = DMLabelGetValue(lbl, c, &val);CHKERRQ(ierr); 871 if (val == defval) continue; 872 873 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 874 for (p = 0; p < closureSize*2; p += 2) { 875 ierr = PetscBTSet(wp, closure[p] - pStart);CHKERRQ(ierr); 876 } 877 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 878 } 879 } 880 } 881 882 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 883 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 884 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 885 ierr = PetscViewerASCIIPrintf(viewer, "\ 886 \\documentclass[tikz]{standalone}\n\n\ 887 \\usepackage{pgflibraryshapes}\n\ 888 \\usetikzlibrary{backgrounds}\n\ 889 \\usetikzlibrary{arrows}\n\ 890 \\begin{document}\n");CHKERRQ(ierr); 891 if (size > 1) { 892 ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 893 for (p = 0; p < size; ++p) { 894 if (p > 0 && p == size-1) { 895 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 896 } else if (p > 0) { 897 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 898 } 899 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 900 } 901 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 902 } 903 if (drawHasse) { 904 PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart)); 905 906 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%D}\n", vStart);CHKERRQ(ierr); 907 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%D}\n", vEnd-1);CHKERRQ(ierr); 908 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%D}\n", vEnd-vStart);CHKERRQ(ierr); 909 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.);CHKERRQ(ierr); 910 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%D}\n", eStart);CHKERRQ(ierr); 911 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%D}\n", eEnd-1);CHKERRQ(ierr); 912 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.);CHKERRQ(ierr); 913 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%D}\n", eEnd-eStart);CHKERRQ(ierr); 914 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%D}\n", cStart);CHKERRQ(ierr); 915 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%D}\n", cEnd-1);CHKERRQ(ierr); 916 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%D}\n", cEnd-cStart);CHKERRQ(ierr); 917 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.);CHKERRQ(ierr); 918 } 919 ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale);CHKERRQ(ierr); 920 921 /* Plot vertices */ 922 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 923 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 924 for (v = vStart; v < vEnd; ++v) { 925 PetscInt off, dof, d; 926 PetscBool isLabeled = PETSC_FALSE; 927 928 if (wp && !PetscBTLookup(wp,v - pStart)) continue; 929 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 930 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 931 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 932 if (PetscUnlikely(dof > 3)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 933 for (d = 0; d < dof; ++d) { 934 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 935 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 936 } 937 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 938 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 939 for (d = 0; d < dof; ++d) { 940 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 941 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]);CHKERRQ(ierr); 942 } 943 if (drawHasse) color = colors[0%numColors]; 944 else color = colors[rank%numColors]; 945 for (l = 0; l < numLabels; ++l) { 946 PetscInt val; 947 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 948 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 949 } 950 if (drawNumbers[0]) { 951 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 952 } else if (drawColors[0]) { 953 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 954 } else { 955 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", v, rank);CHKERRQ(ierr); 956 } 957 } 958 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 959 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 960 /* Plot edges */ 961 if (plotEdges) { 962 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 963 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 964 for (e = eStart; e < eEnd; ++e) { 965 const PetscInt *cone; 966 PetscInt coneSize, offA, offB, dof, d; 967 968 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 969 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 970 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 971 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 972 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 973 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 974 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 975 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 976 for (d = 0; d < dof; ++d) { 977 tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 978 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 979 } 980 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 981 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 982 for (d = 0; d < dof; ++d) { 983 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 984 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr); 985 } 986 if (drawHasse) color = colors[1%numColors]; 987 else color = colors[rank%numColors]; 988 for (l = 0; l < numLabels; ++l) { 989 PetscInt val; 990 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 991 if (val >= 0) {color = lcolors[l%numLColors]; break;} 992 } 993 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 994 } 995 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 996 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 997 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 998 } 999 /* Plot cells */ 1000 if (dim == 3 || !drawNumbers[1]) { 1001 for (e = eStart; e < eEnd; ++e) { 1002 const PetscInt *cone; 1003 1004 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 1005 color = colors[rank%numColors]; 1006 for (l = 0; l < numLabels; ++l) { 1007 PetscInt val; 1008 ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 1009 if (val >= 0) {color = lcolors[l%numLColors]; break;} 1010 } 1011 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 1012 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 1013 } 1014 } else { 1015 DMPolytopeType ct; 1016 1017 /* Drawing a 2D polygon */ 1018 for (c = cStart; c < cEnd; ++c) { 1019 if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1020 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 1021 if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || 1022 ct == DM_POLYTOPE_TRI_PRISM_TENSOR || 1023 ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 1024 const PetscInt *cone; 1025 PetscInt coneSize, e; 1026 1027 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 1028 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 1029 for (e = 0; e < coneSize; ++e) { 1030 const PetscInt *econe; 1031 1032 ierr = DMPlexGetCone(dm, cone[e], &econe);CHKERRQ(ierr); 1033 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); 1034 } 1035 } else { 1036 PetscInt *closure = NULL; 1037 PetscInt closureSize, Nv = 0, v; 1038 1039 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1040 for (p = 0; p < closureSize*2; p += 2) { 1041 const PetscInt point = closure[p]; 1042 1043 if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1044 } 1045 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 1046 for (v = 0; v <= Nv; ++v) { 1047 const PetscInt vertex = closure[v%Nv]; 1048 1049 if (v > 0) { 1050 if (plotEdges) { 1051 const PetscInt *edge; 1052 PetscInt endpoints[2], ne; 1053 1054 endpoints[0] = closure[v-1]; endpoints[1] = vertex; 1055 ierr = DMPlexGetJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr); 1056 if (ne != 1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %D, %D", endpoints[0], endpoints[1]); 1057 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d) -- ", edge[0], rank);CHKERRQ(ierr); 1058 ierr = DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr); 1059 } else { 1060 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr); 1061 } 1062 } 1063 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", vertex, rank);CHKERRQ(ierr); 1064 } 1065 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ";\n");CHKERRQ(ierr); 1066 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1067 } 1068 } 1069 } 1070 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1071 for (c = cStart; c < cEnd; ++c) { 1072 double ccoords[3] = {0.0, 0.0, 0.0}; 1073 PetscBool isLabeled = PETSC_FALSE; 1074 PetscInt *closure = NULL; 1075 PetscInt closureSize, dof, d, n = 0; 1076 1077 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 1078 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1079 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 1080 for (p = 0; p < closureSize*2; p += 2) { 1081 const PetscInt point = closure[p]; 1082 PetscInt off; 1083 1084 if ((point < vStart) || (point >= vEnd)) continue; 1085 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 1086 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 1087 for (d = 0; d < dof; ++d) { 1088 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1089 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1090 } 1091 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1092 if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1093 for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 1094 ++n; 1095 } 1096 for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 1097 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1098 for (d = 0; d < dof; ++d) { 1099 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 1100 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]);CHKERRQ(ierr); 1101 } 1102 if (drawHasse) color = colors[depth%numColors]; 1103 else color = colors[rank%numColors]; 1104 for (l = 0; l < numLabels; ++l) { 1105 PetscInt val; 1106 ierr = DMGetLabelValue(dm, names[l], c, &val);CHKERRQ(ierr); 1107 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 1108 } 1109 if (drawNumbers[dim]) { 1110 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c);CHKERRQ(ierr); 1111 } else if (drawColors[dim]) { 1112 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 1113 } else { 1114 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", c, rank);CHKERRQ(ierr); 1115 } 1116 } 1117 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1118 if (drawHasse) { 1119 color = colors[depth%numColors]; 1120 ierr = PetscViewerASCIIPrintf(viewer, "%% Cells\n");CHKERRQ(ierr); 1121 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n");CHKERRQ(ierr); 1122 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1123 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); 1124 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1125 1126 color = colors[1%numColors]; 1127 ierr = PetscViewerASCIIPrintf(viewer, "%% Edges\n");CHKERRQ(ierr); 1128 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n");CHKERRQ(ierr); 1129 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1130 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); 1131 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1132 1133 color = colors[0%numColors]; 1134 ierr = PetscViewerASCIIPrintf(viewer, "%% Vertices\n");CHKERRQ(ierr); 1135 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n");CHKERRQ(ierr); 1136 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1137 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); 1138 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1139 1140 for (p = pStart; p < pEnd; ++p) { 1141 const PetscInt *cone; 1142 PetscInt coneSize, cp; 1143 1144 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1145 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1146 for (cp = 0; cp < coneSize; ++cp) { 1147 ierr = PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%D_%d) -- (%D_%d);\n", cone[cp], rank, p, rank);CHKERRQ(ierr); 1148 } 1149 } 1150 } 1151 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1152 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 1153 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 1154 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 1155 for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 1156 for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 1157 for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 1158 ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 1159 ierr = PetscBTDestroy(&wp);CHKERRQ(ierr); 1160 } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 1161 Vec cown,acown; 1162 VecScatter sct; 1163 ISLocalToGlobalMapping g2l; 1164 IS gid,acis; 1165 MPI_Comm comm,ncomm = MPI_COMM_NULL; 1166 MPI_Group ggroup,ngroup; 1167 PetscScalar *array,nid; 1168 const PetscInt *idxs; 1169 PetscInt *idxs2,*start,*adjacency,*work; 1170 PetscInt64 lm[3],gm[3]; 1171 PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 1172 PetscMPIInt d1,d2,rank; 1173 1174 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1175 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 1176 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1177 ierr = MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm);CHKERRMPI(ierr); 1178 #endif 1179 if (ncomm != MPI_COMM_NULL) { 1180 ierr = MPI_Comm_group(comm,&ggroup);CHKERRMPI(ierr); 1181 ierr = MPI_Comm_group(ncomm,&ngroup);CHKERRMPI(ierr); 1182 d1 = 0; 1183 ierr = MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2);CHKERRMPI(ierr); 1184 nid = d2; 1185 ierr = MPI_Group_free(&ggroup);CHKERRMPI(ierr); 1186 ierr = MPI_Group_free(&ngroup);CHKERRMPI(ierr); 1187 ierr = MPI_Comm_free(&ncomm);CHKERRMPI(ierr); 1188 } else nid = 0.0; 1189 1190 /* Get connectivity */ 1191 ierr = DMPlexGetVTKCellHeight(dm,&cellHeight);CHKERRQ(ierr); 1192 ierr = DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid);CHKERRQ(ierr); 1193 1194 /* filter overlapped local cells */ 1195 ierr = DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd);CHKERRQ(ierr); 1196 ierr = ISGetIndices(gid,&idxs);CHKERRQ(ierr); 1197 ierr = ISGetLocalSize(gid,&cum);CHKERRQ(ierr); 1198 ierr = PetscMalloc1(cum,&idxs2);CHKERRQ(ierr); 1199 for (c = cStart, cum = 0; c < cEnd; c++) { 1200 if (idxs[c-cStart] < 0) continue; 1201 idxs2[cum++] = idxs[c-cStart]; 1202 } 1203 ierr = ISRestoreIndices(gid,&idxs);CHKERRQ(ierr); 1204 if (numVertices != cum) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum); 1205 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1206 ierr = ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid);CHKERRQ(ierr); 1207 1208 /* support for node-aware cell locality */ 1209 ierr = ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis);CHKERRQ(ierr); 1210 ierr = VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown);CHKERRQ(ierr); 1211 ierr = VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown);CHKERRQ(ierr); 1212 ierr = VecGetArray(cown,&array);CHKERRQ(ierr); 1213 for (c = 0; c < numVertices; c++) array[c] = nid; 1214 ierr = VecRestoreArray(cown,&array);CHKERRQ(ierr); 1215 ierr = VecScatterCreate(cown,acis,acown,NULL,&sct);CHKERRQ(ierr); 1216 ierr = VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1217 ierr = VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1218 ierr = ISDestroy(&acis);CHKERRQ(ierr); 1219 ierr = VecScatterDestroy(&sct);CHKERRQ(ierr); 1220 ierr = VecDestroy(&cown);CHKERRQ(ierr); 1221 1222 /* compute edgeCut */ 1223 for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 1224 ierr = PetscMalloc1(cum,&work);CHKERRQ(ierr); 1225 ierr = ISLocalToGlobalMappingCreateIS(gid,&g2l);CHKERRQ(ierr); 1226 ierr = ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 1227 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1228 ierr = VecGetArray(acown,&array);CHKERRQ(ierr); 1229 for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 1230 PetscInt totl; 1231 1232 totl = start[c+1]-start[c]; 1233 ierr = ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work);CHKERRQ(ierr); 1234 for (i = 0; i < totl; i++) { 1235 if (work[i] < 0) { 1236 ect += 1; 1237 ectn += (array[i + start[c]] != nid) ? 0 : 1; 1238 } 1239 } 1240 } 1241 ierr = PetscFree(work);CHKERRQ(ierr); 1242 ierr = VecRestoreArray(acown,&array);CHKERRQ(ierr); 1243 lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 1244 lm[1] = -numVertices; 1245 ierr = MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm);CHKERRMPI(ierr); 1246 ierr = PetscViewerASCIIPrintf(viewer," Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]);CHKERRQ(ierr); 1247 lm[0] = ect; /* edgeCut */ 1248 lm[1] = ectn; /* node-aware edgeCut */ 1249 lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 1250 ierr = MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr); 1251 ierr = PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]);CHKERRQ(ierr); 1252 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1253 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); 1254 #else 1255 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0);CHKERRQ(ierr); 1256 #endif 1257 ierr = ISLocalToGlobalMappingDestroy(&g2l);CHKERRQ(ierr); 1258 ierr = PetscFree(start);CHKERRQ(ierr); 1259 ierr = PetscFree(adjacency);CHKERRQ(ierr); 1260 ierr = VecDestroy(&acown);CHKERRQ(ierr); 1261 } else { 1262 const char *name; 1263 PetscInt *sizes, *hybsizes, *ghostsizes; 1264 PetscInt locDepth, depth, cellHeight, dim, d; 1265 PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1266 PetscInt numLabels, l; 1267 DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1268 MPI_Comm comm; 1269 PetscMPIInt size, rank; 1270 1271 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1272 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1273 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1274 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1275 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 1276 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 1277 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1278 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1279 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 1280 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 1281 ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRMPI(ierr); 1282 ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr); 1283 gcNum = gcEnd - gcStart; 1284 ierr = PetscCalloc3(size,&sizes,size,&hybsizes,size,&ghostsizes);CHKERRQ(ierr); 1285 for (d = 0; d <= depth; d++) { 1286 PetscInt Nc[2] = {0, 0}, ict; 1287 1288 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 1289 if (pStart < pEnd) {ierr = DMPlexGetCellType(dm, pStart, &ct0);CHKERRQ(ierr);} 1290 ict = ct0; 1291 ierr = MPI_Bcast(&ict, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1292 ct0 = (DMPolytopeType) ict; 1293 for (p = pStart; p < pEnd; ++p) { 1294 DMPolytopeType ct; 1295 1296 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 1297 if (ct == ct0) ++Nc[0]; 1298 else ++Nc[1]; 1299 } 1300 ierr = MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1301 ierr = MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1302 if (d == depth) {ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);} 1303 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", (depth == 1) && d ? dim : d);CHKERRQ(ierr); 1304 for (p = 0; p < size; ++p) { 1305 if (rank == 0) { 1306 ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]);CHKERRQ(ierr); 1307 if (hybsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]);CHKERRQ(ierr);} 1308 if (ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);} 1309 } 1310 } 1311 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 1312 } 1313 ierr = PetscFree3(sizes,hybsizes,ghostsizes);CHKERRQ(ierr); 1314 { 1315 const PetscReal *maxCell; 1316 const PetscReal *L; 1317 const DMBoundaryType *bd; 1318 PetscBool per, localized; 1319 1320 ierr = DMGetPeriodicity(dm, &per, &maxCell, &L, &bd);CHKERRQ(ierr); 1321 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 1322 if (per) { 1323 ierr = PetscViewerASCIIPrintf(viewer, "Periodic mesh (");CHKERRQ(ierr); 1324 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1325 for (d = 0; d < dim; ++d) { 1326 if (bd && d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1327 if (bd) {ierr = PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]]);CHKERRQ(ierr);} 1328 } 1329 ierr = PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized");CHKERRQ(ierr); 1330 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1331 } 1332 } 1333 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 1334 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 1335 for (l = 0; l < numLabels; ++l) { 1336 DMLabel label; 1337 const char *name; 1338 IS valueIS; 1339 const PetscInt *values; 1340 PetscInt numValues, v; 1341 1342 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 1343 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1344 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 1345 ierr = PetscViewerASCIIPrintf(viewer, " %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr); 1346 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 1347 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 1348 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1349 for (v = 0; v < numValues; ++v) { 1350 PetscInt size; 1351 1352 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 1353 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1354 ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr); 1355 } 1356 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 1357 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1358 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 1359 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 1360 } 1361 { 1362 char **labelNames; 1363 PetscInt Nl = numLabels; 1364 PetscBool flg; 1365 1366 ierr = PetscMalloc1(Nl, &labelNames);CHKERRQ(ierr); 1367 ierr = PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg);CHKERRQ(ierr); 1368 for (l = 0; l < Nl; ++l) { 1369 DMLabel label; 1370 1371 ierr = DMHasLabel(dm, labelNames[l], &flg);CHKERRQ(ierr); 1372 if (flg) { 1373 ierr = DMGetLabel(dm, labelNames[l], &label);CHKERRQ(ierr); 1374 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 1375 } 1376 ierr = PetscFree(labelNames[l]);CHKERRQ(ierr); 1377 } 1378 ierr = PetscFree(labelNames);CHKERRQ(ierr); 1379 } 1380 /* If no fields are specified, people do not want to see adjacency */ 1381 if (dm->Nf) { 1382 PetscInt f; 1383 1384 for (f = 0; f < dm->Nf; ++f) { 1385 const char *name; 1386 1387 ierr = PetscObjectGetName(dm->fields[f].disc, &name);CHKERRQ(ierr); 1388 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Field %s:\n", name);CHKERRQ(ierr);} 1389 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1390 if (dm->fields[f].label) {ierr = DMLabelView(dm->fields[f].label, viewer);CHKERRQ(ierr);} 1391 if (dm->fields[f].adjacency[0]) { 1392 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n");CHKERRQ(ierr);} 1393 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM\n");CHKERRQ(ierr);} 1394 } else { 1395 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FEM\n");CHKERRQ(ierr);} 1396 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n");CHKERRQ(ierr);} 1397 } 1398 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1399 } 1400 } 1401 ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr); 1402 if (cdm) { 1403 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1404 ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr); 1405 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1406 } 1407 } 1408 PetscFunctionReturn(0); 1409 } 1410 1411 static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1412 { 1413 DMPolytopeType ct; 1414 PetscMPIInt rank; 1415 PetscErrorCode ierr; 1416 1417 PetscFunctionBegin; 1418 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1419 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1420 switch (ct) { 1421 case DM_POLYTOPE_TRIANGLE: 1422 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1423 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1424 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1425 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1426 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1427 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1428 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1429 break; 1430 case DM_POLYTOPE_QUADRILATERAL: 1431 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1432 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1433 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1434 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1435 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1436 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1437 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1438 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1439 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1440 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1441 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1442 ierr = PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1443 break; 1444 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1445 } 1446 PetscFunctionReturn(0); 1447 } 1448 1449 static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1450 { 1451 DMPolytopeType ct; 1452 PetscReal centroid[2] = {0., 0.}; 1453 PetscMPIInt rank; 1454 PetscInt fillColor, v, e, d; 1455 PetscErrorCode ierr; 1456 1457 PetscFunctionBegin; 1458 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1459 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1460 fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2; 1461 switch (ct) { 1462 case DM_POLYTOPE_TRIANGLE: 1463 { 1464 PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1465 1466 for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;} 1467 for (e = 0; e < 3; ++e) { 1468 refCoords[0] = refVertices[e*2+0]; 1469 refCoords[1] = refVertices[e*2+1]; 1470 for (d = 1; d <= edgeDiv; ++d) { 1471 refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv; 1472 refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv; 1473 } 1474 ierr = DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords);CHKERRQ(ierr); 1475 for (d = 0; d < edgeDiv; ++d) { 1476 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); 1477 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); 1478 } 1479 } 1480 } 1481 break; 1482 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1483 } 1484 PetscFunctionReturn(0); 1485 } 1486 1487 static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1488 { 1489 PetscDraw draw; 1490 DM cdm; 1491 PetscSection coordSection; 1492 Vec coordinates; 1493 const PetscScalar *coords; 1494 PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1495 PetscReal *refCoords, *edgeCoords; 1496 PetscBool isnull, drawAffine = PETSC_TRUE; 1497 PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1498 PetscErrorCode ierr; 1499 1500 PetscFunctionBegin; 1501 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 1502 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim); 1503 ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL);CHKERRQ(ierr); 1504 if (!drawAffine) {ierr = PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords);CHKERRQ(ierr);} 1505 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 1506 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1507 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 1508 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1509 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1510 1511 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 1512 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 1513 if (isnull) PetscFunctionReturn(0); 1514 ierr = PetscDrawSetTitle(draw, "Mesh");CHKERRQ(ierr); 1515 1516 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 1517 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 1518 for (c = 0; c < N; c += dim) { 1519 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 1520 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1521 } 1522 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 1523 ierr = MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1524 ierr = MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1525 ierr = PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]);CHKERRQ(ierr); 1526 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 1527 1528 for (c = cStart; c < cEnd; ++c) { 1529 PetscScalar *coords = NULL; 1530 PetscInt numCoords; 1531 1532 ierr = DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords);CHKERRQ(ierr); 1533 if (drawAffine) { 1534 ierr = DMPlexDrawCell(dm, draw, c, coords);CHKERRQ(ierr); 1535 } else { 1536 ierr = DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords);CHKERRQ(ierr); 1537 } 1538 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 1539 } 1540 if (!drawAffine) {ierr = PetscFree2(refCoords, edgeCoords);CHKERRQ(ierr);} 1541 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1542 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 1543 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 1544 PetscFunctionReturn(0); 1545 } 1546 1547 #if defined(PETSC_HAVE_EXODUSII) 1548 #include <exodusII.h> 1549 #include <petscviewerexodusii.h> 1550 #endif 1551 1552 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1553 { 1554 PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1555 char name[PETSC_MAX_PATH_LEN]; 1556 PetscErrorCode ierr; 1557 1558 PetscFunctionBegin; 1559 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1560 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1561 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1562 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1563 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1564 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 1565 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 1566 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus);CHKERRQ(ierr); 1567 if (iascii) { 1568 PetscViewerFormat format; 1569 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1570 if (format == PETSC_VIEWER_ASCII_GLVIS) { 1571 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1572 } else { 1573 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 1574 } 1575 } else if (ishdf5) { 1576 #if defined(PETSC_HAVE_HDF5) 1577 ierr = DMPlexView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1578 #else 1579 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1580 #endif 1581 } else if (isvtk) { 1582 ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr); 1583 } else if (isdraw) { 1584 ierr = DMPlexView_Draw(dm, viewer);CHKERRQ(ierr); 1585 } else if (isglvis) { 1586 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1587 #if defined(PETSC_HAVE_EXODUSII) 1588 } else if (isexodus) { 1589 /* 1590 exodusII requires that all sets be part of exactly one cell set. 1591 If the dm does not have a "Cell Sets" label defined, we create one 1592 with ID 1, containig all cells. 1593 Note that if the Cell Sets label is defined but does not cover all cells, 1594 we may still have a problem. This should probably be checked here or in the viewer; 1595 */ 1596 PetscInt numCS; 1597 ierr = DMGetLabelSize(dm,"Cell Sets",&numCS);CHKERRQ(ierr); 1598 if (!numCS) { 1599 PetscInt cStart, cEnd, c; 1600 ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr); 1601 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1602 for (c = cStart; c < cEnd; ++c) {ierr = DMSetLabelValue(dm, "Cell Sets", c, 1);CHKERRQ(ierr);} 1603 } 1604 ierr = DMView_PlexExodusII(dm, viewer);CHKERRQ(ierr); 1605 #endif 1606 } else { 1607 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1608 } 1609 /* Optionally view the partition */ 1610 ierr = PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg);CHKERRQ(ierr); 1611 if (flg) { 1612 Vec ranks; 1613 ierr = DMPlexCreateRankField(dm, &ranks);CHKERRQ(ierr); 1614 ierr = VecView(ranks, viewer);CHKERRQ(ierr); 1615 ierr = VecDestroy(&ranks);CHKERRQ(ierr); 1616 } 1617 /* Optionally view a label */ 1618 ierr = PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg);CHKERRQ(ierr); 1619 if (flg) { 1620 DMLabel label; 1621 Vec val; 1622 1623 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1624 if (!label) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 1625 ierr = DMPlexCreateLabelField(dm, label, &val);CHKERRQ(ierr); 1626 ierr = VecView(val, viewer);CHKERRQ(ierr); 1627 ierr = VecDestroy(&val);CHKERRQ(ierr); 1628 } 1629 PetscFunctionReturn(0); 1630 } 1631 1632 /*@ 1633 DMPlexTopologyView - Saves a DMPlex topology into a file 1634 1635 Collective on DM 1636 1637 Input Parameters: 1638 + dm - The DM whose topology is to be saved 1639 - viewer - The PetscViewer for saving 1640 1641 Level: advanced 1642 1643 .seealso: DMView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexTopologyLoad() 1644 @*/ 1645 PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 1646 { 1647 PetscBool ishdf5; 1648 PetscErrorCode ierr; 1649 1650 PetscFunctionBegin; 1651 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1652 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1653 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1654 if (ishdf5) { 1655 #if defined(PETSC_HAVE_HDF5) 1656 PetscViewerFormat format; 1657 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1658 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1659 IS globalPointNumbering; 1660 1661 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1662 ierr = DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1663 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1664 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 1665 #else 1666 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1667 #endif 1668 } 1669 PetscFunctionReturn(0); 1670 } 1671 1672 /*@ 1673 DMPlexCoordinatesView - Saves DMPlex coordinates into a file 1674 1675 Collective on DM 1676 1677 Input Parameters: 1678 + dm - The DM whose coordinates are to be saved 1679 - viewer - The PetscViewer for saving 1680 1681 Level: advanced 1682 1683 .seealso: DMView(), DMPlexTopologyView(), DMPlexLabelsView(), DMPlexCoordinatesLoad() 1684 @*/ 1685 PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 1686 { 1687 PetscBool ishdf5; 1688 PetscErrorCode ierr; 1689 1690 PetscFunctionBegin; 1691 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1692 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1693 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1694 if (ishdf5) { 1695 #if defined(PETSC_HAVE_HDF5) 1696 PetscViewerFormat format; 1697 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1698 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1699 ierr = DMPlexCoordinatesView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1700 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1701 #else 1702 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1703 #endif 1704 } 1705 PetscFunctionReturn(0); 1706 } 1707 1708 /*@ 1709 DMPlexLabelsView - Saves DMPlex labels into a file 1710 1711 Collective on DM 1712 1713 Input Parameters: 1714 + dm - The DM whose labels are to be saved 1715 - viewer - The PetscViewer for saving 1716 1717 Level: advanced 1718 1719 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsLoad() 1720 @*/ 1721 PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1722 { 1723 PetscBool ishdf5; 1724 PetscErrorCode ierr; 1725 1726 PetscFunctionBegin; 1727 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1728 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1729 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1730 if (ishdf5) { 1731 #if defined(PETSC_HAVE_HDF5) 1732 IS globalPointNumbering; 1733 PetscViewerFormat format; 1734 1735 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1736 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1737 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1738 ierr = DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1739 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1740 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1741 #else 1742 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1743 #endif 1744 } 1745 PetscFunctionReturn(0); 1746 } 1747 1748 /*@ 1749 DMPlexSectionView - Saves a section associated with a DMPlex 1750 1751 Collective on DM 1752 1753 Input Parameters: 1754 + dm - The DM that contains the topology on which the section to be saved is defined 1755 . viewer - The PetscViewer for saving 1756 - sectiondm - The DM that contains the section to be saved 1757 1758 Level: advanced 1759 1760 Notes: 1761 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. 1762 1763 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. 1764 1765 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexGlobalVectorView(), DMPlexLocalVectorView(), PetscSectionView(), DMPlexSectionLoad() 1766 @*/ 1767 PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1768 { 1769 PetscBool ishdf5; 1770 PetscErrorCode ierr; 1771 1772 PetscFunctionBegin; 1773 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1774 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1775 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1776 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 1777 if (ishdf5) { 1778 #if defined(PETSC_HAVE_HDF5) 1779 ierr = DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm);CHKERRQ(ierr); 1780 #else 1781 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1782 #endif 1783 } 1784 PetscFunctionReturn(0); 1785 } 1786 1787 /*@ 1788 DMPlexGlobalVectorView - Saves a global vector 1789 1790 Collective on DM 1791 1792 Input Parameters: 1793 + dm - The DM that represents the topology 1794 . viewer - The PetscViewer to save data with 1795 . sectiondm - The DM that contains the global section on which vec is defined 1796 - vec - The global vector to be saved 1797 1798 Level: advanced 1799 1800 Notes: 1801 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. 1802 1803 Typical calling sequence 1804 $ DMCreate(PETSC_COMM_WORLD, &dm); 1805 $ DMSetType(dm, DMPLEX); 1806 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1807 $ DMClone(dm, §iondm); 1808 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1809 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1810 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1811 $ PetscSectionSetChart(section, pStart, pEnd); 1812 $ PetscSectionSetUp(section); 1813 $ DMSetLocalSection(sectiondm, section); 1814 $ PetscSectionDestroy(§ion); 1815 $ DMGetGlobalVector(sectiondm, &vec); 1816 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1817 $ DMPlexTopologyView(dm, viewer); 1818 $ DMPlexSectionView(dm, viewer, sectiondm); 1819 $ DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 1820 $ DMRestoreGlobalVector(sectiondm, &vec); 1821 $ DMDestroy(§iondm); 1822 $ DMDestroy(&dm); 1823 1824 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexLocalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1825 @*/ 1826 PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1827 { 1828 PetscBool ishdf5; 1829 PetscErrorCode ierr; 1830 1831 PetscFunctionBegin; 1832 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1833 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1834 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1835 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1836 /* Check consistency */ 1837 { 1838 PetscSection section; 1839 PetscBool includesConstraints; 1840 PetscInt m, m1; 1841 1842 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1843 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 1844 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1845 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1846 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1847 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 1848 } 1849 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1850 if (ishdf5) { 1851 #if defined(PETSC_HAVE_HDF5) 1852 ierr = DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1853 #else 1854 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1855 #endif 1856 } 1857 PetscFunctionReturn(0); 1858 } 1859 1860 /*@ 1861 DMPlexLocalVectorView - Saves a local vector 1862 1863 Collective on DM 1864 1865 Input Parameters: 1866 + dm - The DM that represents the topology 1867 . viewer - The PetscViewer to save data with 1868 . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm 1869 - vec - The local vector to be saved 1870 1871 Level: advanced 1872 1873 Notes: 1874 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. 1875 1876 Typical calling sequence 1877 $ DMCreate(PETSC_COMM_WORLD, &dm); 1878 $ DMSetType(dm, DMPLEX); 1879 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1880 $ DMClone(dm, §iondm); 1881 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1882 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1883 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1884 $ PetscSectionSetChart(section, pStart, pEnd); 1885 $ PetscSectionSetUp(section); 1886 $ DMSetLocalSection(sectiondm, section); 1887 $ DMGetLocalVector(sectiondm, &vec); 1888 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1889 $ DMPlexTopologyView(dm, viewer); 1890 $ DMPlexSectionView(dm, viewer, sectiondm); 1891 $ DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 1892 $ DMRestoreLocalVector(sectiondm, &vec); 1893 $ DMDestroy(§iondm); 1894 $ DMDestroy(&dm); 1895 1896 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexGlobalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1897 @*/ 1898 PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1899 { 1900 PetscBool ishdf5; 1901 PetscErrorCode ierr; 1902 1903 PetscFunctionBegin; 1904 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1905 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1906 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1907 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1908 /* Check consistency */ 1909 { 1910 PetscSection section; 1911 PetscBool includesConstraints; 1912 PetscInt m, m1; 1913 1914 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1915 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 1916 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1917 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1918 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1919 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 1920 } 1921 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1922 if (ishdf5) { 1923 #if defined(PETSC_HAVE_HDF5) 1924 ierr = DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1925 #else 1926 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1927 #endif 1928 } 1929 PetscFunctionReturn(0); 1930 } 1931 1932 PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 1933 { 1934 PetscBool ishdf5; 1935 PetscErrorCode ierr; 1936 1937 PetscFunctionBegin; 1938 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1939 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1940 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1941 if (ishdf5) { 1942 #if defined(PETSC_HAVE_HDF5) 1943 PetscViewerFormat format; 1944 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1945 if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 1946 ierr = DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer);CHKERRQ(ierr); 1947 } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1948 ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1949 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1950 PetscFunctionReturn(0); 1951 #else 1952 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1953 #endif 1954 } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 1955 } 1956 1957 /*@ 1958 DMPlexTopologyLoad - Loads a topology into a DMPlex 1959 1960 Collective on DM 1961 1962 Input Parameters: 1963 + dm - The DM into which the topology is loaded 1964 - viewer - The PetscViewer for the saved topology 1965 1966 Output Parameters: 1967 . 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 1968 1969 Level: advanced 1970 1971 .seealso: DMLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1972 @*/ 1973 PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 1974 { 1975 PetscBool ishdf5; 1976 PetscErrorCode ierr; 1977 1978 PetscFunctionBegin; 1979 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1980 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1981 if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 1982 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1983 if (ishdf5) { 1984 #if defined(PETSC_HAVE_HDF5) 1985 PetscViewerFormat format; 1986 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1987 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1988 ierr = DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 1989 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1990 #else 1991 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1992 #endif 1993 } 1994 PetscFunctionReturn(0); 1995 } 1996 1997 /*@ 1998 DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 1999 2000 Collective on DM 2001 2002 Input Parameters: 2003 + dm - The DM into which the coordinates are loaded 2004 - viewer - The PetscViewer for the saved coordinates 2005 2006 Level: advanced 2007 2008 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2009 @*/ 2010 PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer) 2011 { 2012 PetscBool ishdf5; 2013 PetscErrorCode ierr; 2014 2015 PetscFunctionBegin; 2016 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2017 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2018 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2019 if (ishdf5) { 2020 #if defined(PETSC_HAVE_HDF5) 2021 PetscViewerFormat format; 2022 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2023 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2024 ierr = DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 2025 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2026 #else 2027 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2028 #endif 2029 } 2030 PetscFunctionReturn(0); 2031 } 2032 2033 /*@ 2034 DMPlexLabelsLoad - Loads labels into a DMPlex 2035 2036 Collective on DM 2037 2038 Input Parameters: 2039 + dm - The DM into which the labels are loaded 2040 - viewer - The PetscViewer for the saved labels 2041 2042 Level: advanced 2043 2044 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2045 @*/ 2046 PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer) 2047 { 2048 PetscBool ishdf5; 2049 PetscErrorCode ierr; 2050 2051 PetscFunctionBegin; 2052 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2053 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2054 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2055 if (ishdf5) { 2056 #if defined(PETSC_HAVE_HDF5) 2057 PetscViewerFormat format; 2058 2059 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2060 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2061 ierr = DMPlexLabelsLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 2062 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 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 DMPlexSectionLoad - Loads section into a DMPlex 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 section (sectionA) 2078 . sectiondm - The DM into which the on-disk section (sectionA) is migrated 2079 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2080 2081 Output Parameters 2082 + 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) 2083 - 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) 2084 2085 Level: advanced 2086 2087 Notes: 2088 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. 2089 2090 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. 2091 2092 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. 2093 2094 Example using 2 processes: 2095 $ NX (number of points on dm): 4 2096 $ sectionA : the on-disk section 2097 $ vecA : a vector associated with sectionA 2098 $ sectionB : sectiondm's local section constructed in this function 2099 $ vecB (local) : a vector associated with sectiondm's local section 2100 $ vecB (global) : a vector associated with sectiondm's global section 2101 $ 2102 $ rank 0 rank 1 2103 $ vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2104 $ sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2105 $ sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2106 $ sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2107 $ [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2108 $ sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2109 $ sectionB->atlasDof : 1 0 1 | 1 3 2110 $ sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2111 $ vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2112 $ vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2113 $ 2114 $ where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2115 2116 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad(), PetscSectionLoad(), DMPlexSectionView() 2117 @*/ 2118 PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2119 { 2120 PetscBool ishdf5; 2121 PetscErrorCode ierr; 2122 2123 PetscFunctionBegin; 2124 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2125 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2126 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2127 PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 2128 if (globalDofSF) PetscValidPointer(globalDofSF, 5); 2129 if (localDofSF) PetscValidPointer(localDofSF, 6); 2130 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2131 if (ishdf5) { 2132 #if defined(PETSC_HAVE_HDF5) 2133 ierr = DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF);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 DMPlexGlobalVectorLoad - Loads on-disk vector data into a global 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 global section on which vec is defined 2150 . sf - The SF that migrates the on-disk vector data into vec 2151 - vec - The global 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, &gsf, NULL); 2166 $ DMGetGlobalVector(sectiondm, &vec); 2167 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2168 $ DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2169 $ DMRestoreGlobalVector(sectiondm, &vec); 2170 $ PetscSFDestroy(&gsf); 2171 $ PetscSFDestroy(&sfX); 2172 $ DMDestroy(§iondm); 2173 $ DMDestroy(&dm); 2174 2175 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexLocalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2176 @*/ 2177 PetscErrorCode DMPlexGlobalVectorLoad(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 = DMGetGlobalSection(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, "Global vector size (%D) != global 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 /*@ 2213 DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 2214 2215 Collective on DM 2216 2217 Input Parameters: 2218 + dm - The DM that represents the topology 2219 . viewer - The PetscViewer that represents the on-disk vector data 2220 . sectiondm - The DM that contains the local section on which vec is defined 2221 . sf - The SF that migrates the on-disk vector data into vec 2222 - vec - The local vector to set values of 2223 2224 Level: advanced 2225 2226 Notes: 2227 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. 2228 2229 Typical calling sequence 2230 $ DMCreate(PETSC_COMM_WORLD, &dm); 2231 $ DMSetType(dm, DMPLEX); 2232 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2233 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2234 $ DMClone(dm, §iondm); 2235 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2236 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2237 $ DMGetLocalVector(sectiondm, &vec); 2238 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2239 $ DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2240 $ DMRestoreLocalVector(sectiondm, &vec); 2241 $ PetscSFDestroy(&lsf); 2242 $ PetscSFDestroy(&sfX); 2243 $ DMDestroy(§iondm); 2244 $ DMDestroy(&dm); 2245 2246 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexGlobalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2247 @*/ 2248 PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2249 { 2250 PetscBool ishdf5; 2251 PetscErrorCode ierr; 2252 2253 PetscFunctionBegin; 2254 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2255 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2256 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2257 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2258 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2259 /* Check consistency */ 2260 { 2261 PetscSection section; 2262 PetscBool includesConstraints; 2263 PetscInt m, m1; 2264 2265 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2266 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 2267 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2268 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2269 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2270 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 2271 } 2272 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2273 if (ishdf5) { 2274 #if defined(PETSC_HAVE_HDF5) 2275 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2276 #else 2277 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2278 #endif 2279 } 2280 PetscFunctionReturn(0); 2281 } 2282 2283 PetscErrorCode DMDestroy_Plex(DM dm) 2284 { 2285 DM_Plex *mesh = (DM_Plex*) dm->data; 2286 PetscErrorCode ierr; 2287 2288 PetscFunctionBegin; 2289 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr); 2290 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr); 2291 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL);CHKERRQ(ierr); 2292 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL);CHKERRQ(ierr); 2293 if (--mesh->refct > 0) PetscFunctionReturn(0); 2294 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 2295 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 2296 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 2297 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 2298 ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr); 2299 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 2300 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 2301 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 2302 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 2303 ierr = PetscFree(mesh->transformType);CHKERRQ(ierr); 2304 ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 2305 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 2306 ierr = ISDestroy(&mesh->subpointIS);CHKERRQ(ierr); 2307 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 2308 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 2309 ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 2310 ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 2311 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 2312 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 2313 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 2314 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 2315 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 2316 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 2317 ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr); 2318 ierr = PetscFree(mesh->neighbors);CHKERRQ(ierr); 2319 if (mesh->metricCtx) { ierr = PetscFree(mesh->metricCtx);CHKERRQ(ierr); } 2320 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 2321 ierr = PetscFree(mesh);CHKERRQ(ierr); 2322 PetscFunctionReturn(0); 2323 } 2324 2325 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2326 { 2327 PetscSection sectionGlobal; 2328 PetscInt bs = -1, mbs; 2329 PetscInt localSize; 2330 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2331 PetscErrorCode ierr; 2332 MatType mtype; 2333 ISLocalToGlobalMapping ltog; 2334 2335 PetscFunctionBegin; 2336 ierr = MatInitializePackage();CHKERRQ(ierr); 2337 mtype = dm->mattype; 2338 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 2339 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 2340 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 2341 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 2342 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 2343 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 2344 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 2345 ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr); 2346 if (mbs > 1) bs = mbs; 2347 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 2348 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 2349 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 2350 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 2351 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 2352 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 2353 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 2354 ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr); 2355 if (!isShell) { 2356 PetscSection subSection; 2357 PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 2358 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *ltogidx, lsize; 2359 PetscInt pStart, pEnd, p, dof, cdof; 2360 2361 /* Set localtoglobalmapping on the matrix for MatSetValuesLocal() to work (it also creates the local matrices in case of MATIS) */ 2362 if (isMatIS) { /* need a different l2g map than the one computed by DMGetLocalToGlobalMapping */ 2363 PetscSection section; 2364 PetscInt size; 2365 2366 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 2367 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 2368 ierr = PetscMalloc1(size,<ogidx);CHKERRQ(ierr); 2369 ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr); 2370 } else { 2371 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 2372 } 2373 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 2374 for (p = pStart, lsize = 0; p < pEnd; ++p) { 2375 PetscInt bdof; 2376 2377 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 2378 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 2379 dof = dof < 0 ? -(dof+1) : dof; 2380 bdof = cdof && (dof-cdof) ? 1 : dof; 2381 if (dof) { 2382 if (bs < 0) {bs = bdof;} 2383 else if (bs != bdof) {bs = 1; if (!isMatIS) break;} 2384 } 2385 if (isMatIS) { 2386 PetscInt loff,c,off; 2387 ierr = PetscSectionGetOffset(subSection, p, &loff);CHKERRQ(ierr); 2388 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 2389 for (c = 0; c < dof-cdof; ++c, ++lsize) ltogidx[loff+c] = off > -1 ? off+c : -(off+1)+c; 2390 } 2391 } 2392 /* Must have same blocksize on all procs (some might have no points) */ 2393 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 2394 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 2395 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 2396 else {bs = bsMinMax[0];} 2397 bs = PetscMax(1,bs); 2398 if (isMatIS) { /* Must reduce indices by blocksize */ 2399 PetscInt l; 2400 2401 lsize = lsize/bs; 2402 if (bs > 1) for (l = 0; l < lsize; ++l) ltogidx[l] = ltogidx[l*bs]/bs; 2403 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, lsize, ltogidx, PETSC_OWN_POINTER, <og);CHKERRQ(ierr); 2404 } 2405 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 2406 if (isMatIS) { 2407 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 2408 } 2409 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 2410 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 2411 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 2412 } 2413 ierr = MatSetDM(*J, dm);CHKERRQ(ierr); 2414 PetscFunctionReturn(0); 2415 } 2416 2417 /*@ 2418 DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2419 2420 Not collective 2421 2422 Input Parameter: 2423 . mesh - The DMPlex 2424 2425 Output Parameters: 2426 . subsection - The subdomain section 2427 2428 Level: developer 2429 2430 .seealso: 2431 @*/ 2432 PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2433 { 2434 DM_Plex *mesh = (DM_Plex*) dm->data; 2435 PetscErrorCode ierr; 2436 2437 PetscFunctionBegin; 2438 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2439 if (!mesh->subdomainSection) { 2440 PetscSection section; 2441 PetscSF sf; 2442 2443 ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr); 2444 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 2445 ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr); 2446 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 2447 } 2448 *subsection = mesh->subdomainSection; 2449 PetscFunctionReturn(0); 2450 } 2451 2452 /*@ 2453 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2454 2455 Not collective 2456 2457 Input Parameter: 2458 . mesh - The DMPlex 2459 2460 Output Parameters: 2461 + pStart - The first mesh point 2462 - pEnd - The upper bound for mesh points 2463 2464 Level: beginner 2465 2466 .seealso: DMPlexCreate(), DMPlexSetChart() 2467 @*/ 2468 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2469 { 2470 DM_Plex *mesh = (DM_Plex*) dm->data; 2471 PetscErrorCode ierr; 2472 2473 PetscFunctionBegin; 2474 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2475 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2476 PetscFunctionReturn(0); 2477 } 2478 2479 /*@ 2480 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2481 2482 Not collective 2483 2484 Input Parameters: 2485 + mesh - The DMPlex 2486 . pStart - The first mesh point 2487 - pEnd - The upper bound for mesh points 2488 2489 Output Parameters: 2490 2491 Level: beginner 2492 2493 .seealso: DMPlexCreate(), DMPlexGetChart() 2494 @*/ 2495 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2496 { 2497 DM_Plex *mesh = (DM_Plex*) dm->data; 2498 PetscErrorCode ierr; 2499 2500 PetscFunctionBegin; 2501 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2502 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2503 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 2504 PetscFunctionReturn(0); 2505 } 2506 2507 /*@ 2508 DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2509 2510 Not collective 2511 2512 Input Parameters: 2513 + mesh - The DMPlex 2514 - p - The point, which must lie in the chart set with DMPlexSetChart() 2515 2516 Output Parameter: 2517 . size - The cone size for point p 2518 2519 Level: beginner 2520 2521 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2522 @*/ 2523 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2524 { 2525 DM_Plex *mesh = (DM_Plex*) dm->data; 2526 PetscErrorCode ierr; 2527 2528 PetscFunctionBegin; 2529 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2530 PetscValidPointer(size, 3); 2531 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2532 PetscFunctionReturn(0); 2533 } 2534 2535 /*@ 2536 DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2537 2538 Not collective 2539 2540 Input Parameters: 2541 + mesh - The DMPlex 2542 . p - The point, which must lie in the chart set with DMPlexSetChart() 2543 - size - The cone size for point p 2544 2545 Output Parameter: 2546 2547 Note: 2548 This should be called after DMPlexSetChart(). 2549 2550 Level: beginner 2551 2552 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 2553 @*/ 2554 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2555 { 2556 DM_Plex *mesh = (DM_Plex*) dm->data; 2557 PetscErrorCode ierr; 2558 2559 PetscFunctionBegin; 2560 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2561 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2562 2563 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 2564 PetscFunctionReturn(0); 2565 } 2566 2567 /*@ 2568 DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2569 2570 Not collective 2571 2572 Input Parameters: 2573 + mesh - The DMPlex 2574 . p - The point, which must lie in the chart set with DMPlexSetChart() 2575 - size - The additional cone size for point p 2576 2577 Output Parameter: 2578 2579 Note: 2580 This should be called after DMPlexSetChart(). 2581 2582 Level: beginner 2583 2584 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 2585 @*/ 2586 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2587 { 2588 DM_Plex *mesh = (DM_Plex*) dm->data; 2589 PetscInt csize; 2590 PetscErrorCode ierr; 2591 2592 PetscFunctionBegin; 2593 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2594 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2595 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 2596 2597 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 2598 PetscFunctionReturn(0); 2599 } 2600 2601 /*@C 2602 DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2603 2604 Not collective 2605 2606 Input Parameters: 2607 + dm - The DMPlex 2608 - p - The point, which must lie in the chart set with DMPlexSetChart() 2609 2610 Output Parameter: 2611 . cone - An array of points which are on the in-edges for point p 2612 2613 Level: beginner 2614 2615 Fortran Notes: 2616 Since it returns an array, this routine is only available in Fortran 90, and you must 2617 include petsc.h90 in your code. 2618 You must also call DMPlexRestoreCone() after you finish using the returned array. 2619 DMPlexRestoreCone() is not needed/available in C. 2620 2621 .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart() 2622 @*/ 2623 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2624 { 2625 DM_Plex *mesh = (DM_Plex*) dm->data; 2626 PetscInt off; 2627 PetscErrorCode ierr; 2628 2629 PetscFunctionBegin; 2630 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2631 PetscValidPointer(cone, 3); 2632 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2633 *cone = &mesh->cones[off]; 2634 PetscFunctionReturn(0); 2635 } 2636 2637 /*@C 2638 DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 2639 2640 Not collective 2641 2642 Input Parameters: 2643 + dm - The DMPlex 2644 - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 2645 2646 Output Parameters: 2647 + pConesSection - PetscSection describing the layout of pCones 2648 - pCones - An array of points which are on the in-edges for the point set p 2649 2650 Level: intermediate 2651 2652 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart() 2653 @*/ 2654 PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 2655 { 2656 PetscSection cs, newcs; 2657 PetscInt *cones; 2658 PetscInt *newarr=NULL; 2659 PetscInt n; 2660 PetscErrorCode ierr; 2661 2662 PetscFunctionBegin; 2663 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 2664 ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr); 2665 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 2666 if (pConesSection) *pConesSection = newcs; 2667 if (pCones) { 2668 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 2669 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr); 2670 } 2671 PetscFunctionReturn(0); 2672 } 2673 2674 /*@ 2675 DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2676 2677 Not collective 2678 2679 Input Parameters: 2680 + dm - The DMPlex 2681 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2682 2683 Output Parameter: 2684 . expandedPoints - An array of vertices recursively expanded from input points 2685 2686 Level: advanced 2687 2688 Notes: 2689 Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2690 There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2691 2692 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth() 2693 @*/ 2694 PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2695 { 2696 IS *expandedPointsAll; 2697 PetscInt depth; 2698 PetscErrorCode ierr; 2699 2700 PetscFunctionBegin; 2701 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2702 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2703 PetscValidPointer(expandedPoints, 3); 2704 ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2705 *expandedPoints = expandedPointsAll[0]; 2706 ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]);CHKERRQ(ierr); 2707 ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2708 PetscFunctionReturn(0); 2709 } 2710 2711 /*@ 2712 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). 2713 2714 Not collective 2715 2716 Input Parameters: 2717 + dm - The DMPlex 2718 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2719 2720 Output Parameters: 2721 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2722 . expandedPoints - (optional) An array of index sets with recursively expanded cones 2723 - sections - (optional) An array of sections which describe mappings from points to their cone points 2724 2725 Level: advanced 2726 2727 Notes: 2728 Like DMPlexGetConeTuple() but recursive. 2729 2730 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. 2731 For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2732 2733 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: 2734 (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2735 (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2736 2737 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2738 @*/ 2739 PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2740 { 2741 const PetscInt *arr0=NULL, *cone=NULL; 2742 PetscInt *arr=NULL, *newarr=NULL; 2743 PetscInt d, depth_, i, n, newn, cn, co, start, end; 2744 IS *expandedPoints_; 2745 PetscSection *sections_; 2746 PetscErrorCode ierr; 2747 2748 PetscFunctionBegin; 2749 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2750 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2751 if (depth) PetscValidIntPointer(depth, 3); 2752 if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2753 if (sections) PetscValidPointer(sections, 5); 2754 ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr); 2755 ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr); 2756 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2757 ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr); 2758 ierr = PetscCalloc1(depth_, §ions_);CHKERRQ(ierr); 2759 arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2760 for (d=depth_-1; d>=0; d--) { 2761 ierr = PetscSectionCreate(PETSC_COMM_SELF, §ions_[d]);CHKERRQ(ierr); 2762 ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr); 2763 for (i=0; i<n; i++) { 2764 ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr); 2765 if (arr[i] >= start && arr[i] < end) { 2766 ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr); 2767 ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr); 2768 } else { 2769 ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr); 2770 } 2771 } 2772 ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr); 2773 ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr); 2774 ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr); 2775 for (i=0; i<n; i++) { 2776 ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr); 2777 ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr); 2778 if (cn > 1) { 2779 ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr); 2780 ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr); 2781 } else { 2782 newarr[co] = arr[i]; 2783 } 2784 } 2785 ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr); 2786 arr = newarr; 2787 n = newn; 2788 } 2789 ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr); 2790 *depth = depth_; 2791 if (expandedPoints) *expandedPoints = expandedPoints_; 2792 else { 2793 for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);} 2794 ierr = PetscFree(expandedPoints_);CHKERRQ(ierr); 2795 } 2796 if (sections) *sections = sections_; 2797 else { 2798 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(§ions_[d]);CHKERRQ(ierr);} 2799 ierr = PetscFree(sections_);CHKERRQ(ierr); 2800 } 2801 PetscFunctionReturn(0); 2802 } 2803 2804 /*@ 2805 DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2806 2807 Not collective 2808 2809 Input Parameters: 2810 + dm - The DMPlex 2811 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2812 2813 Output Parameters: 2814 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2815 . expandedPoints - (optional) An array of recursively expanded cones 2816 - sections - (optional) An array of sections which describe mappings from points to their cone points 2817 2818 Level: advanced 2819 2820 Notes: 2821 See DMPlexGetConeRecursive() for details. 2822 2823 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2824 @*/ 2825 PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2826 { 2827 PetscInt d, depth_; 2828 PetscErrorCode ierr; 2829 2830 PetscFunctionBegin; 2831 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2832 if (depth && *depth != depth_) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2833 if (depth) *depth = 0; 2834 if (expandedPoints) { 2835 for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);} 2836 ierr = PetscFree(*expandedPoints);CHKERRQ(ierr); 2837 } 2838 if (sections) { 2839 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);} 2840 ierr = PetscFree(*sections);CHKERRQ(ierr); 2841 } 2842 PetscFunctionReturn(0); 2843 } 2844 2845 /*@ 2846 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 2847 2848 Not collective 2849 2850 Input Parameters: 2851 + mesh - The DMPlex 2852 . p - The point, which must lie in the chart set with DMPlexSetChart() 2853 - cone - An array of points which are on the in-edges for point p 2854 2855 Output Parameter: 2856 2857 Note: 2858 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2859 2860 Level: beginner 2861 2862 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize() 2863 @*/ 2864 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 2865 { 2866 DM_Plex *mesh = (DM_Plex*) dm->data; 2867 PetscInt pStart, pEnd; 2868 PetscInt dof, off, c; 2869 PetscErrorCode ierr; 2870 2871 PetscFunctionBegin; 2872 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2873 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2874 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2875 if (dof) PetscValidPointer(cone, 3); 2876 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2877 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); 2878 for (c = 0; c < dof; ++c) { 2879 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); 2880 mesh->cones[off+c] = cone[c]; 2881 } 2882 PetscFunctionReturn(0); 2883 } 2884 2885 /*@C 2886 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 2887 2888 Not collective 2889 2890 Input Parameters: 2891 + mesh - The DMPlex 2892 - p - The point, which must lie in the chart set with DMPlexSetChart() 2893 2894 Output Parameter: 2895 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2896 integer giving the prescription for cone traversal. 2897 2898 Level: beginner 2899 2900 Notes: 2901 The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 2902 the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 2903 of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 2904 with the identity. 2905 2906 Fortran Notes: 2907 Since it returns an array, this routine is only available in Fortran 90, and you must 2908 include petsc.h90 in your code. 2909 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 2910 DMPlexRestoreConeOrientation() is not needed/available in C. 2911 2912 .seealso: DMPolytopeTypeComposeOrientation(), DMPolytopeTypeComposeOrientationInv(), DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 2913 @*/ 2914 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 2915 { 2916 DM_Plex *mesh = (DM_Plex*) dm->data; 2917 PetscInt off; 2918 PetscErrorCode ierr; 2919 2920 PetscFunctionBegin; 2921 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2922 if (PetscDefined(USE_DEBUG)) { 2923 PetscInt dof; 2924 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2925 if (dof) PetscValidPointer(coneOrientation, 3); 2926 } 2927 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2928 2929 *coneOrientation = &mesh->coneOrientations[off]; 2930 PetscFunctionReturn(0); 2931 } 2932 2933 /*@ 2934 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 2935 2936 Not collective 2937 2938 Input Parameters: 2939 + mesh - The DMPlex 2940 . p - The point, which must lie in the chart set with DMPlexSetChart() 2941 - coneOrientation - An array of orientations 2942 Output Parameter: 2943 2944 Notes: 2945 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2946 2947 The meaning of coneOrientation is detailed in DMPlexGetConeOrientation(). 2948 2949 Level: beginner 2950 2951 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2952 @*/ 2953 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 2954 { 2955 DM_Plex *mesh = (DM_Plex*) dm->data; 2956 PetscInt pStart, pEnd; 2957 PetscInt dof, off, c; 2958 PetscErrorCode ierr; 2959 2960 PetscFunctionBegin; 2961 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2962 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2963 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2964 if (dof) PetscValidPointer(coneOrientation, 3); 2965 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2966 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); 2967 for (c = 0; c < dof; ++c) { 2968 PetscInt cdof, o = coneOrientation[c]; 2969 2970 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 2971 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); 2972 mesh->coneOrientations[off+c] = o; 2973 } 2974 PetscFunctionReturn(0); 2975 } 2976 2977 /*@ 2978 DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 2979 2980 Not collective 2981 2982 Input Parameters: 2983 + mesh - The DMPlex 2984 . p - The point, which must lie in the chart set with DMPlexSetChart() 2985 . conePos - The local index in the cone where the point should be put 2986 - conePoint - The mesh point to insert 2987 2988 Level: beginner 2989 2990 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2991 @*/ 2992 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 2993 { 2994 DM_Plex *mesh = (DM_Plex*) dm->data; 2995 PetscInt pStart, pEnd; 2996 PetscInt dof, off; 2997 PetscErrorCode ierr; 2998 2999 PetscFunctionBegin; 3000 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3001 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3002 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); 3003 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); 3004 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3005 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3006 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); 3007 mesh->cones[off+conePos] = conePoint; 3008 PetscFunctionReturn(0); 3009 } 3010 3011 /*@ 3012 DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 3013 3014 Not collective 3015 3016 Input Parameters: 3017 + mesh - The DMPlex 3018 . p - The point, which must lie in the chart set with DMPlexSetChart() 3019 . conePos - The local index in the cone where the point should be put 3020 - coneOrientation - The point orientation to insert 3021 3022 Level: beginner 3023 3024 Notes: 3025 The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation(). 3026 3027 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3028 @*/ 3029 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3030 { 3031 DM_Plex *mesh = (DM_Plex*) dm->data; 3032 PetscInt pStart, pEnd; 3033 PetscInt dof, off; 3034 PetscErrorCode ierr; 3035 3036 PetscFunctionBegin; 3037 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3038 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3039 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); 3040 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3041 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3042 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); 3043 mesh->coneOrientations[off+conePos] = coneOrientation; 3044 PetscFunctionReturn(0); 3045 } 3046 3047 /*@ 3048 DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3049 3050 Not collective 3051 3052 Input Parameters: 3053 + mesh - The DMPlex 3054 - p - The point, which must lie in the chart set with DMPlexSetChart() 3055 3056 Output Parameter: 3057 . size - The support size for point p 3058 3059 Level: beginner 3060 3061 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 3062 @*/ 3063 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3064 { 3065 DM_Plex *mesh = (DM_Plex*) dm->data; 3066 PetscErrorCode ierr; 3067 3068 PetscFunctionBegin; 3069 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3070 PetscValidPointer(size, 3); 3071 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3072 PetscFunctionReturn(0); 3073 } 3074 3075 /*@ 3076 DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3077 3078 Not collective 3079 3080 Input Parameters: 3081 + mesh - The DMPlex 3082 . p - The point, which must lie in the chart set with DMPlexSetChart() 3083 - size - The support size for point p 3084 3085 Output Parameter: 3086 3087 Note: 3088 This should be called after DMPlexSetChart(). 3089 3090 Level: beginner 3091 3092 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 3093 @*/ 3094 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3095 { 3096 DM_Plex *mesh = (DM_Plex*) dm->data; 3097 PetscErrorCode ierr; 3098 3099 PetscFunctionBegin; 3100 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3101 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3102 3103 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 3104 PetscFunctionReturn(0); 3105 } 3106 3107 /*@C 3108 DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3109 3110 Not collective 3111 3112 Input Parameters: 3113 + mesh - The DMPlex 3114 - p - The point, which must lie in the chart set with DMPlexSetChart() 3115 3116 Output Parameter: 3117 . support - An array of points which are on the out-edges for point p 3118 3119 Level: beginner 3120 3121 Fortran Notes: 3122 Since it returns an array, this routine is only available in Fortran 90, and you must 3123 include petsc.h90 in your code. 3124 You must also call DMPlexRestoreSupport() after you finish using the returned array. 3125 DMPlexRestoreSupport() is not needed/available in C. 3126 3127 .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart() 3128 @*/ 3129 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3130 { 3131 DM_Plex *mesh = (DM_Plex*) dm->data; 3132 PetscInt off; 3133 PetscErrorCode ierr; 3134 3135 PetscFunctionBegin; 3136 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3137 PetscValidPointer(support, 3); 3138 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3139 *support = &mesh->supports[off]; 3140 PetscFunctionReturn(0); 3141 } 3142 3143 /*@ 3144 DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 3145 3146 Not collective 3147 3148 Input Parameters: 3149 + mesh - The DMPlex 3150 . p - The point, which must lie in the chart set with DMPlexSetChart() 3151 - support - An array of points which are on the out-edges for point p 3152 3153 Output Parameter: 3154 3155 Note: 3156 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 3157 3158 Level: beginner 3159 3160 .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 3161 @*/ 3162 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3163 { 3164 DM_Plex *mesh = (DM_Plex*) dm->data; 3165 PetscInt pStart, pEnd; 3166 PetscInt dof, off, c; 3167 PetscErrorCode ierr; 3168 3169 PetscFunctionBegin; 3170 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3171 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3172 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3173 if (dof) PetscValidPointer(support, 3); 3174 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3175 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); 3176 for (c = 0; c < dof; ++c) { 3177 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); 3178 mesh->supports[off+c] = support[c]; 3179 } 3180 PetscFunctionReturn(0); 3181 } 3182 3183 /*@ 3184 DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 3185 3186 Not collective 3187 3188 Input Parameters: 3189 + mesh - The DMPlex 3190 . p - The point, which must lie in the chart set with DMPlexSetChart() 3191 . supportPos - The local index in the cone where the point should be put 3192 - supportPoint - The mesh point to insert 3193 3194 Level: beginner 3195 3196 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3197 @*/ 3198 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3199 { 3200 DM_Plex *mesh = (DM_Plex*) dm->data; 3201 PetscInt pStart, pEnd; 3202 PetscInt dof, off; 3203 PetscErrorCode ierr; 3204 3205 PetscFunctionBegin; 3206 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3207 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3208 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3209 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3210 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); 3211 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); 3212 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); 3213 mesh->supports[off+supportPos] = supportPoint; 3214 PetscFunctionReturn(0); 3215 } 3216 3217 /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3218 PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3219 { 3220 switch (ct) { 3221 case DM_POLYTOPE_SEGMENT: 3222 if (o == -1) return -2; 3223 break; 3224 case DM_POLYTOPE_TRIANGLE: 3225 if (o == -3) return -1; 3226 if (o == -2) return -3; 3227 if (o == -1) return -2; 3228 break; 3229 case DM_POLYTOPE_QUADRILATERAL: 3230 if (o == -4) return -2; 3231 if (o == -3) return -1; 3232 if (o == -2) return -4; 3233 if (o == -1) return -3; 3234 break; 3235 default: return o; 3236 } 3237 return o; 3238 } 3239 3240 /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3241 PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3242 { 3243 switch (ct) { 3244 case DM_POLYTOPE_SEGMENT: 3245 if ((o == -2) || (o == 1)) return -1; 3246 if (o == -1) return 0; 3247 break; 3248 case DM_POLYTOPE_TRIANGLE: 3249 if (o == -3) return -2; 3250 if (o == -2) return -1; 3251 if (o == -1) return -3; 3252 break; 3253 case DM_POLYTOPE_QUADRILATERAL: 3254 if (o == -4) return -2; 3255 if (o == -3) return -1; 3256 if (o == -2) return -4; 3257 if (o == -1) return -3; 3258 break; 3259 default: return o; 3260 } 3261 return o; 3262 } 3263 3264 /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3265 PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3266 { 3267 PetscInt pStart, pEnd, p; 3268 PetscErrorCode ierr; 3269 3270 PetscFunctionBegin; 3271 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3272 for (p = pStart; p < pEnd; ++p) { 3273 const PetscInt *cone, *ornt; 3274 PetscInt coneSize, c; 3275 3276 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3277 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 3278 ierr = DMPlexGetConeOrientation(dm, p, &ornt);CHKERRQ(ierr); 3279 for (c = 0; c < coneSize; ++c) { 3280 DMPolytopeType ct; 3281 const PetscInt o = ornt[c]; 3282 3283 ierr = DMPlexGetCellType(dm, cone[c], &ct);CHKERRQ(ierr); 3284 switch (ct) { 3285 case DM_POLYTOPE_SEGMENT: 3286 if ((o == -2) || (o == 1)) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3287 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, 0);CHKERRQ(ierr);} 3288 break; 3289 case DM_POLYTOPE_TRIANGLE: 3290 if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);} 3291 if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3292 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);} 3293 break; 3294 case DM_POLYTOPE_QUADRILATERAL: 3295 if (o == -4) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);} 3296 if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3297 if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -4);CHKERRQ(ierr);} 3298 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);} 3299 break; 3300 default: break; 3301 } 3302 } 3303 } 3304 PetscFunctionReturn(0); 3305 } 3306 3307 static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3308 { 3309 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3310 PetscInt *closure; 3311 const PetscInt *tmp = NULL, *tmpO = NULL; 3312 PetscInt off = 0, tmpSize, t; 3313 PetscErrorCode ierr; 3314 3315 PetscFunctionBeginHot; 3316 if (ornt) { 3317 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3318 if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3319 } 3320 if (*points) { 3321 closure = *points; 3322 } else { 3323 PetscInt maxConeSize, maxSupportSize; 3324 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3325 ierr = DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure);CHKERRQ(ierr); 3326 } 3327 if (useCone) { 3328 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 3329 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 3330 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 3331 } else { 3332 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 3333 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 3334 } 3335 if (ct == DM_POLYTOPE_UNKNOWN) { 3336 closure[off++] = p; 3337 closure[off++] = 0; 3338 for (t = 0; t < tmpSize; ++t) { 3339 closure[off++] = tmp[t]; 3340 closure[off++] = tmpO ? tmpO[t] : 0; 3341 } 3342 } else { 3343 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);CHKERRQ(ierr); 3344 3345 /* We assume that cells with a valid type have faces with a valid type */ 3346 closure[off++] = p; 3347 closure[off++] = ornt; 3348 for (t = 0; t < tmpSize; ++t) { 3349 DMPolytopeType ft; 3350 3351 ierr = DMPlexGetCellType(dm, tmp[t], &ft);CHKERRQ(ierr); 3352 closure[off++] = tmp[arr[t]]; 3353 closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3354 } 3355 } 3356 if (numPoints) *numPoints = tmpSize+1; 3357 if (points) *points = closure; 3358 PetscFunctionReturn(0); 3359 } 3360 3361 /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */ 3362 static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3363 { 3364 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3365 const PetscInt *cone, *ornt; 3366 PetscInt *pts, *closure = NULL; 3367 DMPolytopeType ft; 3368 PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3369 PetscInt dim, coneSize, c, d, clSize, cl; 3370 PetscErrorCode ierr; 3371 3372 PetscFunctionBeginHot; 3373 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3374 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 3375 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3376 ierr = DMPlexGetConeOrientation(dm, point, &ornt);CHKERRQ(ierr); 3377 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3378 coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim+1)-1)/(maxConeSize-1)) : dim+1; 3379 supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1; 3380 maxSize = PetscMax(coneSeries, supportSeries); 3381 if (*points) {pts = *points;} 3382 else {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts);CHKERRQ(ierr);} 3383 c = 0; 3384 pts[c++] = point; 3385 pts[c++] = o; 3386 ierr = DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft);CHKERRQ(ierr); 3387 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure);CHKERRQ(ierr); 3388 for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 3389 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure);CHKERRQ(ierr); 3390 for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 3391 ierr = DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure);CHKERRQ(ierr); 3392 for (d = 2; d < coneSize; ++d) { 3393 ierr = DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft);CHKERRQ(ierr); 3394 pts[c++] = cone[arr[d*2+0]]; 3395 pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]); 3396 } 3397 if (dim >= 3) { 3398 for (d = 2; d < coneSize; ++d) { 3399 const PetscInt fpoint = cone[arr[d*2+0]]; 3400 const PetscInt *fcone, *fornt; 3401 PetscInt fconeSize, fc, i; 3402 3403 ierr = DMPlexGetCellType(dm, fpoint, &ft);CHKERRQ(ierr); 3404 const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d])); 3405 ierr = DMPlexGetConeSize(dm, fpoint, &fconeSize);CHKERRQ(ierr); 3406 ierr = DMPlexGetCone(dm, fpoint, &fcone);CHKERRQ(ierr); 3407 ierr = DMPlexGetConeOrientation(dm, fpoint, &fornt);CHKERRQ(ierr); 3408 for (fc = 0; fc < fconeSize; ++fc) { 3409 const PetscInt cp = fcone[farr[fc*2+0]]; 3410 const PetscInt co = farr[fc*2+1]; 3411 3412 for (i = 0; i < c; i += 2) if (pts[i] == cp) break; 3413 if (i == c) { 3414 ierr = DMPlexGetCellType(dm, cp, &ft);CHKERRQ(ierr); 3415 pts[c++] = cp; 3416 pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]); 3417 } 3418 } 3419 } 3420 } 3421 *numPoints = c/2; 3422 *points = pts; 3423 PetscFunctionReturn(0); 3424 } 3425 3426 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3427 { 3428 DMPolytopeType ct; 3429 PetscInt *closure, *fifo; 3430 PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3431 PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3432 PetscInt depth, maxSize; 3433 PetscErrorCode ierr; 3434 3435 PetscFunctionBeginHot; 3436 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3437 if (depth == 1) { 3438 ierr = DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points);CHKERRQ(ierr); 3439 PetscFunctionReturn(0); 3440 } 3441 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3442 if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3443 if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 3444 ierr = DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points);CHKERRQ(ierr); 3445 PetscFunctionReturn(0); 3446 } 3447 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3448 coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth+1)-1)/(maxConeSize-1)) : depth+1; 3449 supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1; 3450 maxSize = PetscMax(coneSeries, supportSeries); 3451 ierr = DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3452 if (*points) {closure = *points;} 3453 else {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure);CHKERRQ(ierr);} 3454 closure[closureSize++] = p; 3455 closure[closureSize++] = ornt; 3456 fifo[fifoSize++] = p; 3457 fifo[fifoSize++] = ornt; 3458 fifo[fifoSize++] = ct; 3459 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3460 while (fifoSize - fifoStart) { 3461 const PetscInt q = fifo[fifoStart++]; 3462 const PetscInt o = fifo[fifoStart++]; 3463 const DMPolytopeType qt = (DMPolytopeType) fifo[fifoStart++]; 3464 const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 3465 const PetscInt *tmp, *tmpO; 3466 PetscInt tmpSize, t; 3467 3468 if (PetscDefined(USE_DEBUG)) { 3469 PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2; 3470 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); 3471 } 3472 if (useCone) { 3473 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 3474 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 3475 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 3476 } else { 3477 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 3478 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 3479 tmpO = NULL; 3480 } 3481 for (t = 0; t < tmpSize; ++t) { 3482 const PetscInt ip = useCone && qarr ? qarr[t*2] : t; 3483 const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0; 3484 const PetscInt cp = tmp[ip]; 3485 ierr = DMPlexGetCellType(dm, cp, &ct);CHKERRQ(ierr); 3486 const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3487 PetscInt c; 3488 3489 /* Check for duplicate */ 3490 for (c = 0; c < closureSize; c += 2) { 3491 if (closure[c] == cp) break; 3492 } 3493 if (c == closureSize) { 3494 closure[closureSize++] = cp; 3495 closure[closureSize++] = co; 3496 fifo[fifoSize++] = cp; 3497 fifo[fifoSize++] = co; 3498 fifo[fifoSize++] = ct; 3499 } 3500 } 3501 } 3502 ierr = DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3503 if (numPoints) *numPoints = closureSize/2; 3504 if (points) *points = closure; 3505 PetscFunctionReturn(0); 3506 } 3507 3508 /*@C 3509 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3510 3511 Not collective 3512 3513 Input Parameters: 3514 + dm - The DMPlex 3515 . p - The mesh point 3516 - useCone - PETSC_TRUE for the closure, otherwise return the star 3517 3518 Input/Output Parameter: 3519 . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 3520 if NULL on input, internal storage will be returned, otherwise the provided array is used 3521 3522 Output Parameter: 3523 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3524 3525 Note: 3526 If using internal storage (points is NULL on input), each call overwrites the last output. 3527 3528 Fortran Notes: 3529 Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3530 3531 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3532 3533 Level: beginner 3534 3535 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3536 @*/ 3537 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3538 { 3539 PetscErrorCode ierr; 3540 3541 PetscFunctionBeginHot; 3542 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3543 if (numPoints) PetscValidIntPointer(numPoints, 4); 3544 if (points) PetscValidPointer(points, 5); 3545 ierr = DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points);CHKERRQ(ierr); 3546 PetscFunctionReturn(0); 3547 } 3548 3549 /*@C 3550 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3551 3552 Not collective 3553 3554 Input Parameters: 3555 + dm - The DMPlex 3556 . p - The mesh point 3557 . useCone - PETSC_TRUE for the closure, otherwise return the star 3558 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3559 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3560 3561 Note: 3562 If not using internal storage (points is not NULL on input), this call is unnecessary 3563 3564 Fortran Notes: 3565 Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3566 3567 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3568 3569 Level: beginner 3570 3571 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3572 @*/ 3573 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3574 { 3575 PetscErrorCode ierr; 3576 3577 PetscFunctionBeginHot; 3578 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3579 if (numPoints) *numPoints = 0; 3580 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr); 3581 PetscFunctionReturn(0); 3582 } 3583 3584 /*@ 3585 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3586 3587 Not collective 3588 3589 Input Parameter: 3590 . mesh - The DMPlex 3591 3592 Output Parameters: 3593 + maxConeSize - The maximum number of in-edges 3594 - maxSupportSize - The maximum number of out-edges 3595 3596 Level: beginner 3597 3598 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 3599 @*/ 3600 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3601 { 3602 DM_Plex *mesh = (DM_Plex*) dm->data; 3603 3604 PetscFunctionBegin; 3605 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3606 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 3607 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 3608 PetscFunctionReturn(0); 3609 } 3610 3611 PetscErrorCode DMSetUp_Plex(DM dm) 3612 { 3613 DM_Plex *mesh = (DM_Plex*) dm->data; 3614 PetscInt size; 3615 PetscErrorCode ierr; 3616 3617 PetscFunctionBegin; 3618 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3619 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 3620 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 3621 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 3622 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 3623 ierr = PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt));CHKERRQ(ierr); 3624 if (mesh->maxSupportSize) { 3625 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3626 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 3627 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 3628 ierr = PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt));CHKERRQ(ierr); 3629 } 3630 PetscFunctionReturn(0); 3631 } 3632 3633 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3634 { 3635 PetscErrorCode ierr; 3636 3637 PetscFunctionBegin; 3638 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 3639 ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 3640 if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3641 if (dm->useNatural && dm->sfMigration) { 3642 PetscSF sfMigrationInv,sfNatural; 3643 PetscSection section, sectionSeq; 3644 3645 (*subdm)->sfMigration = dm->sfMigration; 3646 ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr); 3647 ierr = DMGetLocalSection((*subdm), §ion);CHKERRQ(ierr); 3648 ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3649 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq);CHKERRQ(ierr); 3650 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3651 3652 ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3653 (*subdm)->sfNatural = sfNatural; 3654 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3655 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3656 } 3657 PetscFunctionReturn(0); 3658 } 3659 3660 PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 3661 { 3662 PetscErrorCode ierr; 3663 PetscInt i = 0; 3664 3665 PetscFunctionBegin; 3666 ierr = DMClone(dms[0], superdm);CHKERRQ(ierr); 3667 ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr); 3668 (*superdm)->useNatural = PETSC_FALSE; 3669 for (i = 0; i < len; i++) { 3670 if (dms[i]->useNatural && dms[i]->sfMigration) { 3671 PetscSF sfMigrationInv,sfNatural; 3672 PetscSection section, sectionSeq; 3673 3674 (*superdm)->sfMigration = dms[i]->sfMigration; 3675 ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr); 3676 (*superdm)->useNatural = PETSC_TRUE; 3677 ierr = DMGetLocalSection((*superdm), §ion);CHKERRQ(ierr); 3678 ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3679 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq);CHKERRQ(ierr); 3680 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3681 3682 ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3683 (*superdm)->sfNatural = sfNatural; 3684 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3685 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3686 break; 3687 } 3688 } 3689 PetscFunctionReturn(0); 3690 } 3691 3692 /*@ 3693 DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3694 3695 Not collective 3696 3697 Input Parameter: 3698 . mesh - The DMPlex 3699 3700 Output Parameter: 3701 3702 Note: 3703 This should be called after all calls to DMPlexSetCone() 3704 3705 Level: beginner 3706 3707 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 3708 @*/ 3709 PetscErrorCode DMPlexSymmetrize(DM dm) 3710 { 3711 DM_Plex *mesh = (DM_Plex*) dm->data; 3712 PetscInt *offsets; 3713 PetscInt supportSize; 3714 PetscInt pStart, pEnd, p; 3715 PetscErrorCode ierr; 3716 3717 PetscFunctionBegin; 3718 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3719 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 3720 ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3721 /* Calculate support sizes */ 3722 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3723 for (p = pStart; p < pEnd; ++p) { 3724 PetscInt dof, off, c; 3725 3726 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3727 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3728 for (c = off; c < off+dof; ++c) { 3729 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 3730 } 3731 } 3732 for (p = pStart; p < pEnd; ++p) { 3733 PetscInt dof; 3734 3735 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3736 3737 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 3738 } 3739 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3740 /* Calculate supports */ 3741 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 3742 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 3743 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 3744 for (p = pStart; p < pEnd; ++p) { 3745 PetscInt dof, off, c; 3746 3747 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3748 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3749 for (c = off; c < off+dof; ++c) { 3750 const PetscInt q = mesh->cones[c]; 3751 PetscInt offS; 3752 3753 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 3754 3755 mesh->supports[offS+offsets[q]] = p; 3756 ++offsets[q]; 3757 } 3758 } 3759 ierr = PetscFree(offsets);CHKERRQ(ierr); 3760 ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3761 PetscFunctionReturn(0); 3762 } 3763 3764 static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3765 { 3766 IS stratumIS; 3767 PetscErrorCode ierr; 3768 3769 PetscFunctionBegin; 3770 if (pStart >= pEnd) PetscFunctionReturn(0); 3771 if (PetscDefined(USE_DEBUG)) { 3772 PetscInt qStart, qEnd, numLevels, level; 3773 PetscBool overlap = PETSC_FALSE; 3774 ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr); 3775 for (level = 0; level < numLevels; level++) { 3776 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3777 if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3778 } 3779 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); 3780 } 3781 ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr); 3782 ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr); 3783 ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 3784 PetscFunctionReturn(0); 3785 } 3786 3787 /*@ 3788 DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 3789 can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3790 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3791 the DAG. 3792 3793 Collective on dm 3794 3795 Input Parameter: 3796 . mesh - The DMPlex 3797 3798 Output Parameter: 3799 3800 Notes: 3801 Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3802 meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 3803 until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3804 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3805 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3806 3807 The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3808 if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3809 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 3810 to interpolate only that one (e0), so that 3811 $ cone(c0) = {e0, v2} 3812 $ cone(e0) = {v0, v1} 3813 If DMPlexStratify() is run on this mesh, it will give depths 3814 $ depth 0 = {v0, v1, v2} 3815 $ depth 1 = {e0, c0} 3816 where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3817 3818 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3819 3820 Level: beginner 3821 3822 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes() 3823 @*/ 3824 PetscErrorCode DMPlexStratify(DM dm) 3825 { 3826 DM_Plex *mesh = (DM_Plex*) dm->data; 3827 DMLabel label; 3828 PetscInt pStart, pEnd, p; 3829 PetscInt numRoots = 0, numLeaves = 0; 3830 PetscErrorCode ierr; 3831 3832 PetscFunctionBegin; 3833 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3834 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3835 3836 /* Create depth label */ 3837 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3838 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 3839 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3840 3841 { 3842 /* Initialize roots and count leaves */ 3843 PetscInt sMin = PETSC_MAX_INT; 3844 PetscInt sMax = PETSC_MIN_INT; 3845 PetscInt coneSize, supportSize; 3846 3847 for (p = pStart; p < pEnd; ++p) { 3848 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3849 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3850 if (!coneSize && supportSize) { 3851 sMin = PetscMin(p, sMin); 3852 sMax = PetscMax(p, sMax); 3853 ++numRoots; 3854 } else if (!supportSize && coneSize) { 3855 ++numLeaves; 3856 } else if (!supportSize && !coneSize) { 3857 /* Isolated points */ 3858 sMin = PetscMin(p, sMin); 3859 sMax = PetscMax(p, sMax); 3860 } 3861 } 3862 ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr); 3863 } 3864 3865 if (numRoots + numLeaves == (pEnd - pStart)) { 3866 PetscInt sMin = PETSC_MAX_INT; 3867 PetscInt sMax = PETSC_MIN_INT; 3868 PetscInt coneSize, supportSize; 3869 3870 for (p = pStart; p < pEnd; ++p) { 3871 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3872 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3873 if (!supportSize && coneSize) { 3874 sMin = PetscMin(p, sMin); 3875 sMax = PetscMax(p, sMax); 3876 } 3877 } 3878 ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr); 3879 } else { 3880 PetscInt level = 0; 3881 PetscInt qStart, qEnd, q; 3882 3883 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3884 while (qEnd > qStart) { 3885 PetscInt sMin = PETSC_MAX_INT; 3886 PetscInt sMax = PETSC_MIN_INT; 3887 3888 for (q = qStart; q < qEnd; ++q) { 3889 const PetscInt *support; 3890 PetscInt supportSize, s; 3891 3892 ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr); 3893 ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr); 3894 for (s = 0; s < supportSize; ++s) { 3895 sMin = PetscMin(support[s], sMin); 3896 sMax = PetscMax(support[s], sMax); 3897 } 3898 } 3899 ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr); 3900 ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr); 3901 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3902 } 3903 } 3904 { /* just in case there is an empty process */ 3905 PetscInt numValues, maxValues = 0, v; 3906 3907 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 3908 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 3909 for (v = numValues; v < maxValues; v++) { 3910 ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr); 3911 } 3912 } 3913 ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr); 3914 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3915 PetscFunctionReturn(0); 3916 } 3917 3918 PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 3919 { 3920 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3921 PetscInt dim, depth, pheight, coneSize; 3922 PetscErrorCode ierr; 3923 3924 PetscFunctionBeginHot; 3925 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3926 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3927 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3928 pheight = depth - pdepth; 3929 if (depth <= 1) { 3930 switch (pdepth) { 3931 case 0: ct = DM_POLYTOPE_POINT;break; 3932 case 1: 3933 switch (coneSize) { 3934 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3935 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3936 case 4: 3937 switch (dim) { 3938 case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 3939 case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 3940 default: break; 3941 } 3942 break; 3943 case 5: ct = DM_POLYTOPE_PYRAMID;break; 3944 case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3945 case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 3946 default: break; 3947 } 3948 } 3949 } else { 3950 if (pdepth == 0) { 3951 ct = DM_POLYTOPE_POINT; 3952 } else if (pheight == 0) { 3953 switch (dim) { 3954 case 1: 3955 switch (coneSize) { 3956 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3957 default: break; 3958 } 3959 break; 3960 case 2: 3961 switch (coneSize) { 3962 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3963 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3964 default: break; 3965 } 3966 break; 3967 case 3: 3968 switch (coneSize) { 3969 case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 3970 case 5: 3971 { 3972 const PetscInt *cone; 3973 PetscInt faceConeSize; 3974 3975 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 3976 ierr = DMPlexGetConeSize(dm, cone[0], &faceConeSize);CHKERRQ(ierr); 3977 switch (faceConeSize) { 3978 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3979 case 4: ct = DM_POLYTOPE_PYRAMID;break; 3980 } 3981 } 3982 break; 3983 case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 3984 default: break; 3985 } 3986 break; 3987 default: break; 3988 } 3989 } else if (pheight > 0) { 3990 switch (coneSize) { 3991 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3992 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3993 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3994 default: break; 3995 } 3996 } 3997 } 3998 *pt = ct; 3999 PetscFunctionReturn(0); 4000 } 4001 4002 /*@ 4003 DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4004 4005 Collective on dm 4006 4007 Input Parameter: 4008 . mesh - The DMPlex 4009 4010 DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 4011 4012 Level: developer 4013 4014 Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 4015 internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 4016 automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 4017 4018 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel() 4019 @*/ 4020 PetscErrorCode DMPlexComputeCellTypes(DM dm) 4021 { 4022 DM_Plex *mesh; 4023 DMLabel ctLabel; 4024 PetscInt pStart, pEnd, p; 4025 PetscErrorCode ierr; 4026 4027 PetscFunctionBegin; 4028 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4029 mesh = (DM_Plex *) dm->data; 4030 ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr); 4031 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 4032 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4033 for (p = pStart; p < pEnd; ++p) { 4034 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4035 PetscInt pdepth; 4036 4037 ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr); 4038 ierr = DMPlexComputeCellType_Internal(dm, p, pdepth, &ct);CHKERRQ(ierr); 4039 if (ct == DM_POLYTOPE_UNKNOWN) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p); 4040 ierr = DMLabelSetValue(ctLabel, p, ct);CHKERRQ(ierr); 4041 } 4042 ierr = PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState);CHKERRQ(ierr); 4043 ierr = PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr); 4044 PetscFunctionReturn(0); 4045 } 4046 4047 /*@C 4048 DMPlexGetJoin - Get an array for the join of the set of points 4049 4050 Not Collective 4051 4052 Input Parameters: 4053 + dm - The DMPlex object 4054 . numPoints - The number of input points for the join 4055 - points - The input points 4056 4057 Output Parameters: 4058 + numCoveredPoints - The number of points in the join 4059 - coveredPoints - The points in the join 4060 4061 Level: intermediate 4062 4063 Note: Currently, this is restricted to a single level join 4064 4065 Fortran Notes: 4066 Since it returns an array, this routine is only available in Fortran 90, and you must 4067 include petsc.h90 in your code. 4068 4069 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4070 4071 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 4072 @*/ 4073 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4074 { 4075 DM_Plex *mesh = (DM_Plex*) dm->data; 4076 PetscInt *join[2]; 4077 PetscInt joinSize, i = 0; 4078 PetscInt dof, off, p, c, m; 4079 PetscErrorCode ierr; 4080 4081 PetscFunctionBegin; 4082 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4083 PetscValidIntPointer(points, 3); 4084 PetscValidIntPointer(numCoveredPoints, 4); 4085 PetscValidPointer(coveredPoints, 5); 4086 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4087 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4088 /* Copy in support of first point */ 4089 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 4090 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 4091 for (joinSize = 0; joinSize < dof; ++joinSize) { 4092 join[i][joinSize] = mesh->supports[off+joinSize]; 4093 } 4094 /* Check each successive support */ 4095 for (p = 1; p < numPoints; ++p) { 4096 PetscInt newJoinSize = 0; 4097 4098 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 4099 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 4100 for (c = 0; c < dof; ++c) { 4101 const PetscInt point = mesh->supports[off+c]; 4102 4103 for (m = 0; m < joinSize; ++m) { 4104 if (point == join[i][m]) { 4105 join[1-i][newJoinSize++] = point; 4106 break; 4107 } 4108 } 4109 } 4110 joinSize = newJoinSize; 4111 i = 1-i; 4112 } 4113 *numCoveredPoints = joinSize; 4114 *coveredPoints = join[i]; 4115 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4116 PetscFunctionReturn(0); 4117 } 4118 4119 /*@C 4120 DMPlexRestoreJoin - Restore an array for the join of the set of points 4121 4122 Not Collective 4123 4124 Input Parameters: 4125 + dm - The DMPlex object 4126 . numPoints - The number of input points for the join 4127 - points - The input points 4128 4129 Output Parameters: 4130 + numCoveredPoints - The number of points in the join 4131 - coveredPoints - The points in the join 4132 4133 Fortran Notes: 4134 Since it returns an array, this routine is only available in Fortran 90, and you must 4135 include petsc.h90 in your code. 4136 4137 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4138 4139 Level: intermediate 4140 4141 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 4142 @*/ 4143 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4144 { 4145 PetscErrorCode ierr; 4146 4147 PetscFunctionBegin; 4148 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4149 if (points) PetscValidIntPointer(points,3); 4150 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4151 PetscValidPointer(coveredPoints, 5); 4152 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4153 if (numCoveredPoints) *numCoveredPoints = 0; 4154 PetscFunctionReturn(0); 4155 } 4156 4157 /*@C 4158 DMPlexGetFullJoin - Get an array for the join of the set of points 4159 4160 Not Collective 4161 4162 Input Parameters: 4163 + dm - The DMPlex object 4164 . numPoints - The number of input points for the join 4165 - points - The input points 4166 4167 Output Parameters: 4168 + numCoveredPoints - The number of points in the join 4169 - coveredPoints - The points in the join 4170 4171 Fortran Notes: 4172 Since it returns an array, this routine is only available in Fortran 90, and you must 4173 include petsc.h90 in your code. 4174 4175 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4176 4177 Level: intermediate 4178 4179 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 4180 @*/ 4181 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4182 { 4183 DM_Plex *mesh = (DM_Plex*) dm->data; 4184 PetscInt *offsets, **closures; 4185 PetscInt *join[2]; 4186 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 4187 PetscInt p, d, c, m, ms; 4188 PetscErrorCode ierr; 4189 4190 PetscFunctionBegin; 4191 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4192 PetscValidIntPointer(points, 3); 4193 PetscValidIntPointer(numCoveredPoints, 4); 4194 PetscValidPointer(coveredPoints, 5); 4195 4196 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4197 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 4198 ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4199 ms = mesh->maxSupportSize; 4200 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 4201 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4202 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4203 4204 for (p = 0; p < numPoints; ++p) { 4205 PetscInt closureSize; 4206 4207 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 4208 4209 offsets[p*(depth+2)+0] = 0; 4210 for (d = 0; d < depth+1; ++d) { 4211 PetscInt pStart, pEnd, i; 4212 4213 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 4214 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4215 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4216 offsets[p*(depth+2)+d+1] = i; 4217 break; 4218 } 4219 } 4220 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4221 } 4222 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); 4223 } 4224 for (d = 0; d < depth+1; ++d) { 4225 PetscInt dof; 4226 4227 /* Copy in support of first point */ 4228 dof = offsets[d+1] - offsets[d]; 4229 for (joinSize = 0; joinSize < dof; ++joinSize) { 4230 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4231 } 4232 /* Check each successive cone */ 4233 for (p = 1; p < numPoints && joinSize; ++p) { 4234 PetscInt newJoinSize = 0; 4235 4236 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4237 for (c = 0; c < dof; ++c) { 4238 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4239 4240 for (m = 0; m < joinSize; ++m) { 4241 if (point == join[i][m]) { 4242 join[1-i][newJoinSize++] = point; 4243 break; 4244 } 4245 } 4246 } 4247 joinSize = newJoinSize; 4248 i = 1-i; 4249 } 4250 if (joinSize) break; 4251 } 4252 *numCoveredPoints = joinSize; 4253 *coveredPoints = join[i]; 4254 for (p = 0; p < numPoints; ++p) { 4255 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 4256 } 4257 ierr = PetscFree(closures);CHKERRQ(ierr); 4258 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4259 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4260 PetscFunctionReturn(0); 4261 } 4262 4263 /*@C 4264 DMPlexGetMeet - Get an array for the meet of the set of points 4265 4266 Not Collective 4267 4268 Input Parameters: 4269 + dm - The DMPlex object 4270 . numPoints - The number of input points for the meet 4271 - points - The input points 4272 4273 Output Parameters: 4274 + numCoveredPoints - The number of points in the meet 4275 - coveredPoints - The points in the meet 4276 4277 Level: intermediate 4278 4279 Note: Currently, this is restricted to a single level meet 4280 4281 Fortran Notes: 4282 Since it returns an array, this routine is only available in Fortran 90, and you must 4283 include petsc.h90 in your code. 4284 4285 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4286 4287 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 4288 @*/ 4289 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4290 { 4291 DM_Plex *mesh = (DM_Plex*) dm->data; 4292 PetscInt *meet[2]; 4293 PetscInt meetSize, i = 0; 4294 PetscInt dof, off, p, c, m; 4295 PetscErrorCode ierr; 4296 4297 PetscFunctionBegin; 4298 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4299 PetscValidPointer(points, 3); 4300 PetscValidPointer(numCoveringPoints, 4); 4301 PetscValidPointer(coveringPoints, 5); 4302 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4303 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4304 /* Copy in cone of first point */ 4305 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 4306 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 4307 for (meetSize = 0; meetSize < dof; ++meetSize) { 4308 meet[i][meetSize] = mesh->cones[off+meetSize]; 4309 } 4310 /* Check each successive cone */ 4311 for (p = 1; p < numPoints; ++p) { 4312 PetscInt newMeetSize = 0; 4313 4314 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 4315 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 4316 for (c = 0; c < dof; ++c) { 4317 const PetscInt point = mesh->cones[off+c]; 4318 4319 for (m = 0; m < meetSize; ++m) { 4320 if (point == meet[i][m]) { 4321 meet[1-i][newMeetSize++] = point; 4322 break; 4323 } 4324 } 4325 } 4326 meetSize = newMeetSize; 4327 i = 1-i; 4328 } 4329 *numCoveringPoints = meetSize; 4330 *coveringPoints = meet[i]; 4331 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4332 PetscFunctionReturn(0); 4333 } 4334 4335 /*@C 4336 DMPlexRestoreMeet - Restore an array for the meet of the set of points 4337 4338 Not Collective 4339 4340 Input Parameters: 4341 + dm - The DMPlex object 4342 . numPoints - The number of input points for the meet 4343 - points - The input points 4344 4345 Output Parameters: 4346 + numCoveredPoints - The number of points in the meet 4347 - coveredPoints - The points in the meet 4348 4349 Level: intermediate 4350 4351 Fortran Notes: 4352 Since it returns an array, this routine is only available in Fortran 90, and you must 4353 include petsc.h90 in your code. 4354 4355 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4356 4357 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 4358 @*/ 4359 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4360 { 4361 PetscErrorCode ierr; 4362 4363 PetscFunctionBegin; 4364 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4365 if (points) PetscValidIntPointer(points,3); 4366 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4367 PetscValidPointer(coveredPoints,5); 4368 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4369 if (numCoveredPoints) *numCoveredPoints = 0; 4370 PetscFunctionReturn(0); 4371 } 4372 4373 /*@C 4374 DMPlexGetFullMeet - Get an array for the meet of the set of points 4375 4376 Not Collective 4377 4378 Input Parameters: 4379 + dm - The DMPlex object 4380 . numPoints - The number of input points for the meet 4381 - points - The input points 4382 4383 Output Parameters: 4384 + numCoveredPoints - The number of points in the meet 4385 - coveredPoints - The points in the meet 4386 4387 Level: intermediate 4388 4389 Fortran Notes: 4390 Since it returns an array, this routine is only available in Fortran 90, and you must 4391 include petsc.h90 in your code. 4392 4393 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4394 4395 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 4396 @*/ 4397 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4398 { 4399 DM_Plex *mesh = (DM_Plex*) dm->data; 4400 PetscInt *offsets, **closures; 4401 PetscInt *meet[2]; 4402 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 4403 PetscInt p, h, c, m, mc; 4404 PetscErrorCode ierr; 4405 4406 PetscFunctionBegin; 4407 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4408 PetscValidPointer(points, 3); 4409 PetscValidPointer(numCoveredPoints, 4); 4410 PetscValidPointer(coveredPoints, 5); 4411 4412 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 4413 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 4414 ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4415 mc = mesh->maxConeSize; 4416 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 4417 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4418 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4419 4420 for (p = 0; p < numPoints; ++p) { 4421 PetscInt closureSize; 4422 4423 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 4424 4425 offsets[p*(height+2)+0] = 0; 4426 for (h = 0; h < height+1; ++h) { 4427 PetscInt pStart, pEnd, i; 4428 4429 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 4430 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4431 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4432 offsets[p*(height+2)+h+1] = i; 4433 break; 4434 } 4435 } 4436 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4437 } 4438 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); 4439 } 4440 for (h = 0; h < height+1; ++h) { 4441 PetscInt dof; 4442 4443 /* Copy in cone of first point */ 4444 dof = offsets[h+1] - offsets[h]; 4445 for (meetSize = 0; meetSize < dof; ++meetSize) { 4446 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4447 } 4448 /* Check each successive cone */ 4449 for (p = 1; p < numPoints && meetSize; ++p) { 4450 PetscInt newMeetSize = 0; 4451 4452 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4453 for (c = 0; c < dof; ++c) { 4454 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4455 4456 for (m = 0; m < meetSize; ++m) { 4457 if (point == meet[i][m]) { 4458 meet[1-i][newMeetSize++] = point; 4459 break; 4460 } 4461 } 4462 } 4463 meetSize = newMeetSize; 4464 i = 1-i; 4465 } 4466 if (meetSize) break; 4467 } 4468 *numCoveredPoints = meetSize; 4469 *coveredPoints = meet[i]; 4470 for (p = 0; p < numPoints; ++p) { 4471 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 4472 } 4473 ierr = PetscFree(closures);CHKERRQ(ierr); 4474 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4475 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4476 PetscFunctionReturn(0); 4477 } 4478 4479 /*@C 4480 DMPlexEqual - Determine if two DMs have the same topology 4481 4482 Not Collective 4483 4484 Input Parameters: 4485 + dmA - A DMPlex object 4486 - dmB - A DMPlex object 4487 4488 Output Parameters: 4489 . equal - PETSC_TRUE if the topologies are identical 4490 4491 Level: intermediate 4492 4493 Notes: 4494 We are not solving graph isomorphism, so we do not permutation. 4495 4496 .seealso: DMPlexGetCone() 4497 @*/ 4498 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 4499 { 4500 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 4501 PetscErrorCode ierr; 4502 4503 PetscFunctionBegin; 4504 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 4505 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4506 PetscValidPointer(equal, 3); 4507 4508 *equal = PETSC_FALSE; 4509 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 4510 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 4511 if (depth != depthB) PetscFunctionReturn(0); 4512 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 4513 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 4514 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 4515 for (p = pStart; p < pEnd; ++p) { 4516 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 4517 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 4518 4519 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 4520 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 4521 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 4522 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 4523 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 4524 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 4525 if (coneSize != coneSizeB) PetscFunctionReturn(0); 4526 for (c = 0; c < coneSize; ++c) { 4527 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 4528 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 4529 } 4530 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 4531 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 4532 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 4533 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 4534 if (supportSize != supportSizeB) PetscFunctionReturn(0); 4535 for (s = 0; s < supportSize; ++s) { 4536 if (support[s] != supportB[s]) PetscFunctionReturn(0); 4537 } 4538 } 4539 *equal = PETSC_TRUE; 4540 PetscFunctionReturn(0); 4541 } 4542 4543 /*@C 4544 DMPlexGetNumFaceVertices - Returns the number of vertices on a face 4545 4546 Not Collective 4547 4548 Input Parameters: 4549 + dm - The DMPlex 4550 . cellDim - The cell dimension 4551 - numCorners - The number of vertices on a cell 4552 4553 Output Parameters: 4554 . numFaceVertices - The number of vertices on a face 4555 4556 Level: developer 4557 4558 Notes: 4559 Of course this can only work for a restricted set of symmetric shapes 4560 4561 .seealso: DMPlexGetCone() 4562 @*/ 4563 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4564 { 4565 MPI_Comm comm; 4566 PetscErrorCode ierr; 4567 4568 PetscFunctionBegin; 4569 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4570 PetscValidPointer(numFaceVertices,4); 4571 switch (cellDim) { 4572 case 0: 4573 *numFaceVertices = 0; 4574 break; 4575 case 1: 4576 *numFaceVertices = 1; 4577 break; 4578 case 2: 4579 switch (numCorners) { 4580 case 3: /* triangle */ 4581 *numFaceVertices = 2; /* Edge has 2 vertices */ 4582 break; 4583 case 4: /* quadrilateral */ 4584 *numFaceVertices = 2; /* Edge has 2 vertices */ 4585 break; 4586 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 4587 *numFaceVertices = 3; /* Edge has 3 vertices */ 4588 break; 4589 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 4590 *numFaceVertices = 3; /* Edge has 3 vertices */ 4591 break; 4592 default: 4593 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4594 } 4595 break; 4596 case 3: 4597 switch (numCorners) { 4598 case 4: /* tetradehdron */ 4599 *numFaceVertices = 3; /* Face has 3 vertices */ 4600 break; 4601 case 6: /* tet cohesive cells */ 4602 *numFaceVertices = 4; /* Face has 4 vertices */ 4603 break; 4604 case 8: /* hexahedron */ 4605 *numFaceVertices = 4; /* Face has 4 vertices */ 4606 break; 4607 case 9: /* tet cohesive Lagrange cells */ 4608 *numFaceVertices = 6; /* Face has 6 vertices */ 4609 break; 4610 case 10: /* quadratic tetrahedron */ 4611 *numFaceVertices = 6; /* Face has 6 vertices */ 4612 break; 4613 case 12: /* hex cohesive Lagrange cells */ 4614 *numFaceVertices = 6; /* Face has 6 vertices */ 4615 break; 4616 case 18: /* quadratic tet cohesive Lagrange cells */ 4617 *numFaceVertices = 6; /* Face has 6 vertices */ 4618 break; 4619 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 4620 *numFaceVertices = 9; /* Face has 9 vertices */ 4621 break; 4622 default: 4623 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4624 } 4625 break; 4626 default: 4627 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 4628 } 4629 PetscFunctionReturn(0); 4630 } 4631 4632 /*@ 4633 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4634 4635 Not Collective 4636 4637 Input Parameter: 4638 . dm - The DMPlex object 4639 4640 Output Parameter: 4641 . depthLabel - The DMLabel recording point depth 4642 4643 Level: developer 4644 4645 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), 4646 @*/ 4647 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4648 { 4649 PetscFunctionBegin; 4650 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4651 PetscValidPointer(depthLabel, 2); 4652 *depthLabel = dm->depthLabel; 4653 PetscFunctionReturn(0); 4654 } 4655 4656 /*@ 4657 DMPlexGetDepth - Get the depth of the DAG representing this mesh 4658 4659 Not Collective 4660 4661 Input Parameter: 4662 . dm - The DMPlex object 4663 4664 Output Parameter: 4665 . depth - The number of strata (breadth first levels) in the DAG 4666 4667 Level: developer 4668 4669 Notes: 4670 This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4671 The point depth is described more in detail in DMPlexGetDepthStratum(). 4672 An empty mesh gives -1. 4673 4674 .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize() 4675 @*/ 4676 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4677 { 4678 DMLabel label; 4679 PetscInt d = 0; 4680 PetscErrorCode ierr; 4681 4682 PetscFunctionBegin; 4683 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4684 PetscValidPointer(depth, 2); 4685 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4686 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 4687 *depth = d-1; 4688 PetscFunctionReturn(0); 4689 } 4690 4691 /*@ 4692 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4693 4694 Not Collective 4695 4696 Input Parameters: 4697 + dm - The DMPlex object 4698 - stratumValue - The requested depth 4699 4700 Output Parameters: 4701 + start - The first point at this depth 4702 - end - One beyond the last point at this depth 4703 4704 Notes: 4705 Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4706 often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4707 higher dimension, e.g., "edges". 4708 4709 Level: developer 4710 4711 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate() 4712 @*/ 4713 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4714 { 4715 DMLabel label; 4716 PetscInt pStart, pEnd; 4717 PetscErrorCode ierr; 4718 4719 PetscFunctionBegin; 4720 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4721 if (start) {PetscValidPointer(start, 3); *start = 0;} 4722 if (end) {PetscValidPointer(end, 4); *end = 0;} 4723 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4724 if (pStart == pEnd) PetscFunctionReturn(0); 4725 if (stratumValue < 0) { 4726 if (start) *start = pStart; 4727 if (end) *end = pEnd; 4728 PetscFunctionReturn(0); 4729 } 4730 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4731 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4732 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 4733 PetscFunctionReturn(0); 4734 } 4735 4736 /*@ 4737 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4738 4739 Not Collective 4740 4741 Input Parameters: 4742 + dm - The DMPlex object 4743 - stratumValue - The requested height 4744 4745 Output Parameters: 4746 + start - The first point at this height 4747 - end - One beyond the last point at this height 4748 4749 Notes: 4750 Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4751 points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4752 stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4753 4754 Level: developer 4755 4756 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight() 4757 @*/ 4758 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4759 { 4760 DMLabel label; 4761 PetscInt depth, pStart, pEnd; 4762 PetscErrorCode ierr; 4763 4764 PetscFunctionBegin; 4765 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4766 if (start) {PetscValidPointer(start, 3); *start = 0;} 4767 if (end) {PetscValidPointer(end, 4); *end = 0;} 4768 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4769 if (pStart == pEnd) PetscFunctionReturn(0); 4770 if (stratumValue < 0) { 4771 if (start) *start = pStart; 4772 if (end) *end = pEnd; 4773 PetscFunctionReturn(0); 4774 } 4775 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4776 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4777 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 4778 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 4779 PetscFunctionReturn(0); 4780 } 4781 4782 /*@ 4783 DMPlexGetPointDepth - Get the depth of a given point 4784 4785 Not Collective 4786 4787 Input Parameters: 4788 + dm - The DMPlex object 4789 - point - The point 4790 4791 Output Parameter: 4792 . depth - The depth of the point 4793 4794 Level: intermediate 4795 4796 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight() 4797 @*/ 4798 PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4799 { 4800 PetscErrorCode ierr; 4801 4802 PetscFunctionBegin; 4803 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4804 PetscValidIntPointer(depth, 3); 4805 ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr); 4806 PetscFunctionReturn(0); 4807 } 4808 4809 /*@ 4810 DMPlexGetPointHeight - Get the height of a given point 4811 4812 Not Collective 4813 4814 Input Parameters: 4815 + dm - The DMPlex object 4816 - point - The point 4817 4818 Output Parameter: 4819 . height - The height of the point 4820 4821 Level: intermediate 4822 4823 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth() 4824 @*/ 4825 PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 4826 { 4827 PetscInt n, pDepth; 4828 PetscErrorCode ierr; 4829 4830 PetscFunctionBegin; 4831 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4832 PetscValidIntPointer(height, 3); 4833 ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr); 4834 ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr); 4835 *height = n - 1 - pDepth; /* DAG depth is n-1 */ 4836 PetscFunctionReturn(0); 4837 } 4838 4839 /*@ 4840 DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4841 4842 Not Collective 4843 4844 Input Parameter: 4845 . dm - The DMPlex object 4846 4847 Output Parameter: 4848 . celltypeLabel - The DMLabel recording cell polytope type 4849 4850 Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4851 DMCreateLabel(dm, "celltype") beforehand. 4852 4853 Level: developer 4854 4855 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel() 4856 @*/ 4857 PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4858 { 4859 PetscErrorCode ierr; 4860 4861 PetscFunctionBegin; 4862 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4863 PetscValidPointer(celltypeLabel, 2); 4864 if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);} 4865 *celltypeLabel = dm->celltypeLabel; 4866 PetscFunctionReturn(0); 4867 } 4868 4869 /*@ 4870 DMPlexGetCellType - Get the polytope type of a given cell 4871 4872 Not Collective 4873 4874 Input Parameters: 4875 + dm - The DMPlex object 4876 - cell - The cell 4877 4878 Output Parameter: 4879 . celltype - The polytope type of the cell 4880 4881 Level: intermediate 4882 4883 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth() 4884 @*/ 4885 PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4886 { 4887 DMLabel label; 4888 PetscInt ct; 4889 PetscErrorCode ierr; 4890 4891 PetscFunctionBegin; 4892 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4893 PetscValidPointer(celltype, 3); 4894 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4895 ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr); 4896 if (ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell); 4897 *celltype = (DMPolytopeType) ct; 4898 PetscFunctionReturn(0); 4899 } 4900 4901 /*@ 4902 DMPlexSetCellType - Set the polytope type of a given cell 4903 4904 Not Collective 4905 4906 Input Parameters: 4907 + dm - The DMPlex object 4908 . cell - The cell 4909 - celltype - The polytope type of the cell 4910 4911 Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 4912 is executed. This function will override the computed type. However, if automatic classification will not succeed 4913 and a user wants to manually specify all types, the classification must be disabled by calling 4914 DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 4915 4916 Level: advanced 4917 4918 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel() 4919 @*/ 4920 PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 4921 { 4922 DMLabel label; 4923 PetscErrorCode ierr; 4924 4925 PetscFunctionBegin; 4926 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4927 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4928 ierr = DMLabelSetValue(label, cell, celltype);CHKERRQ(ierr); 4929 PetscFunctionReturn(0); 4930 } 4931 4932 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 4933 { 4934 PetscSection section, s; 4935 Mat m; 4936 PetscInt maxHeight; 4937 PetscErrorCode ierr; 4938 4939 PetscFunctionBegin; 4940 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 4941 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 4942 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 4943 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 4944 ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr); 4945 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 4946 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 4947 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 4948 ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr); 4949 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 4950 ierr = MatDestroy(&m);CHKERRQ(ierr); 4951 4952 ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr); 4953 ierr = DMCreateDS(*cdm);CHKERRQ(ierr); 4954 PetscFunctionReturn(0); 4955 } 4956 4957 PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 4958 { 4959 Vec coordsLocal; 4960 DM coordsDM; 4961 PetscErrorCode ierr; 4962 4963 PetscFunctionBegin; 4964 *field = NULL; 4965 ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr); 4966 ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr); 4967 if (coordsLocal && coordsDM) { 4968 ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr); 4969 } 4970 PetscFunctionReturn(0); 4971 } 4972 4973 /*@C 4974 DMPlexGetConeSection - Return a section which describes the layout of cone data 4975 4976 Not Collective 4977 4978 Input Parameters: 4979 . dm - The DMPlex object 4980 4981 Output Parameter: 4982 . section - The PetscSection object 4983 4984 Level: developer 4985 4986 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 4987 @*/ 4988 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 4989 { 4990 DM_Plex *mesh = (DM_Plex*) dm->data; 4991 4992 PetscFunctionBegin; 4993 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4994 if (section) *section = mesh->coneSection; 4995 PetscFunctionReturn(0); 4996 } 4997 4998 /*@C 4999 DMPlexGetSupportSection - Return a section which describes the layout of support data 5000 5001 Not Collective 5002 5003 Input Parameters: 5004 . dm - The DMPlex object 5005 5006 Output Parameter: 5007 . section - The PetscSection object 5008 5009 Level: developer 5010 5011 .seealso: DMPlexGetConeSection() 5012 @*/ 5013 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5014 { 5015 DM_Plex *mesh = (DM_Plex*) dm->data; 5016 5017 PetscFunctionBegin; 5018 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5019 if (section) *section = mesh->supportSection; 5020 PetscFunctionReturn(0); 5021 } 5022 5023 /*@C 5024 DMPlexGetCones - Return cone data 5025 5026 Not Collective 5027 5028 Input Parameters: 5029 . dm - The DMPlex object 5030 5031 Output Parameter: 5032 . cones - The cone for each point 5033 5034 Level: developer 5035 5036 .seealso: DMPlexGetConeSection() 5037 @*/ 5038 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5039 { 5040 DM_Plex *mesh = (DM_Plex*) dm->data; 5041 5042 PetscFunctionBegin; 5043 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5044 if (cones) *cones = mesh->cones; 5045 PetscFunctionReturn(0); 5046 } 5047 5048 /*@C 5049 DMPlexGetConeOrientations - Return cone orientation data 5050 5051 Not Collective 5052 5053 Input Parameters: 5054 . dm - The DMPlex object 5055 5056 Output Parameter: 5057 . coneOrientations - The array of cone orientations for all points 5058 5059 Level: developer 5060 5061 Notes: 5062 The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation(). 5063 5064 The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation(). 5065 5066 .seealso: DMPlexGetConeSection(), DMPlexGetConeOrientation() 5067 @*/ 5068 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5069 { 5070 DM_Plex *mesh = (DM_Plex*) dm->data; 5071 5072 PetscFunctionBegin; 5073 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5074 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 5075 PetscFunctionReturn(0); 5076 } 5077 5078 /******************************** FEM Support **********************************/ 5079 5080 /* 5081 Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 5082 representing a line in the section. 5083 */ 5084 static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 5085 { 5086 PetscErrorCode ierr; 5087 5088 PetscFunctionBeginHot; 5089 ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr); 5090 if (line < 0) { 5091 *k = 0; 5092 *Nc = 0; 5093 } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 5094 *k = 1; 5095 } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 5096 /* An order k SEM disc has k-1 dofs on an edge */ 5097 ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr); 5098 *k = *k / *Nc + 1; 5099 } 5100 PetscFunctionReturn(0); 5101 } 5102 5103 /*@ 5104 5105 DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5106 lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 5107 section provided (or the section of the DM). 5108 5109 Input Parameters: 5110 + dm - The DM 5111 . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 5112 - section - The PetscSection to reorder, or NULL for the default section 5113 5114 Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5115 degree of the basis. 5116 5117 Example: 5118 A typical interpolated single-quad mesh might order points as 5119 .vb 5120 [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5121 5122 v4 -- e6 -- v3 5123 | | 5124 e7 c0 e8 5125 | | 5126 v1 -- e5 -- v2 5127 .ve 5128 5129 (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5130 dofs in the order of points, e.g., 5131 .vb 5132 c0 -> [0,1,2,3] 5133 v1 -> [4] 5134 ... 5135 e5 -> [8, 9] 5136 .ve 5137 5138 which corresponds to the dofs 5139 .vb 5140 6 10 11 7 5141 13 2 3 15 5142 12 0 1 14 5143 4 8 9 5 5144 .ve 5145 5146 The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5147 .vb 5148 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5149 .ve 5150 5151 After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5152 .vb 5153 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5154 .ve 5155 5156 Level: developer 5157 5158 .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection() 5159 @*/ 5160 PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5161 { 5162 DMLabel label; 5163 PetscInt dim, depth = -1, eStart = -1, Nf; 5164 PetscBool vertexchart; 5165 PetscErrorCode ierr; 5166 5167 PetscFunctionBegin; 5168 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5169 if (dim < 1) PetscFunctionReturn(0); 5170 if (point < 0) { 5171 PetscInt sStart,sEnd; 5172 5173 ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr); 5174 point = sEnd-sStart ? sStart : point; 5175 } 5176 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 5177 if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); } 5178 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5179 if (depth == 1) {eStart = point;} 5180 else if (depth == dim) { 5181 const PetscInt *cone; 5182 5183 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5184 if (dim == 2) eStart = cone[0]; 5185 else if (dim == 3) { 5186 const PetscInt *cone2; 5187 ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 5188 eStart = cone2[0]; 5189 } 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); 5190 } 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); 5191 { /* Determine whether the chart covers all points or just vertices. */ 5192 PetscInt pStart,pEnd,cStart,cEnd; 5193 ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr); 5194 ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr); 5195 if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Just vertices */ 5196 else vertexchart = PETSC_FALSE; /* Assume all interpolated points are in chart */ 5197 } 5198 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5199 for (PetscInt d=1; d<=dim; d++) { 5200 PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5201 PetscInt *perm; 5202 5203 for (f = 0; f < Nf; ++f) { 5204 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5205 size += PetscPowInt(k+1, d)*Nc; 5206 } 5207 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 5208 for (f = 0; f < Nf; ++f) { 5209 switch (d) { 5210 case 1: 5211 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5212 /* 5213 Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5214 We want [ vtx0; edge of length k-1; vtx1 ] 5215 */ 5216 for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5217 for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5218 for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5219 foffset = offset; 5220 break; 5221 case 2: 5222 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 5223 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5224 /* The SEM order is 5225 5226 v_lb, {e_b}, v_rb, 5227 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 5228 v_lt, reverse {e_t}, v_rt 5229 */ 5230 { 5231 const PetscInt of = 0; 5232 const PetscInt oeb = of + PetscSqr(k-1); 5233 const PetscInt oer = oeb + (k-1); 5234 const PetscInt oet = oer + (k-1); 5235 const PetscInt oel = oet + (k-1); 5236 const PetscInt ovlb = oel + (k-1); 5237 const PetscInt ovrb = ovlb + 1; 5238 const PetscInt ovrt = ovrb + 1; 5239 const PetscInt ovlt = ovrt + 1; 5240 PetscInt o; 5241 5242 /* bottom */ 5243 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 5244 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5245 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 5246 /* middle */ 5247 for (i = 0; i < k-1; ++i) { 5248 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 5249 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; 5250 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 5251 } 5252 /* top */ 5253 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 5254 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5255 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 5256 foffset = offset; 5257 } 5258 break; 5259 case 3: 5260 /* The original hex closure is 5261 5262 {c, 5263 f_b, f_t, f_f, f_b, f_r, f_l, 5264 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 5265 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 5266 */ 5267 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5268 /* The SEM order is 5269 Bottom Slice 5270 v_blf, {e^{(k-1)-n}_bf}, v_brf, 5271 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 5272 v_blb, {e_bb}, v_brb, 5273 5274 Middle Slice (j) 5275 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 5276 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 5277 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 5278 5279 Top Slice 5280 v_tlf, {e_tf}, v_trf, 5281 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 5282 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 5283 */ 5284 { 5285 const PetscInt oc = 0; 5286 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 5287 const PetscInt oft = ofb + PetscSqr(k-1); 5288 const PetscInt off = oft + PetscSqr(k-1); 5289 const PetscInt ofk = off + PetscSqr(k-1); 5290 const PetscInt ofr = ofk + PetscSqr(k-1); 5291 const PetscInt ofl = ofr + PetscSqr(k-1); 5292 const PetscInt oebl = ofl + PetscSqr(k-1); 5293 const PetscInt oebb = oebl + (k-1); 5294 const PetscInt oebr = oebb + (k-1); 5295 const PetscInt oebf = oebr + (k-1); 5296 const PetscInt oetf = oebf + (k-1); 5297 const PetscInt oetr = oetf + (k-1); 5298 const PetscInt oetb = oetr + (k-1); 5299 const PetscInt oetl = oetb + (k-1); 5300 const PetscInt oerf = oetl + (k-1); 5301 const PetscInt oelf = oerf + (k-1); 5302 const PetscInt oelb = oelf + (k-1); 5303 const PetscInt oerb = oelb + (k-1); 5304 const PetscInt ovblf = oerb + (k-1); 5305 const PetscInt ovblb = ovblf + 1; 5306 const PetscInt ovbrb = ovblb + 1; 5307 const PetscInt ovbrf = ovbrb + 1; 5308 const PetscInt ovtlf = ovbrf + 1; 5309 const PetscInt ovtrf = ovtlf + 1; 5310 const PetscInt ovtrb = ovtrf + 1; 5311 const PetscInt ovtlb = ovtrb + 1; 5312 PetscInt o, n; 5313 5314 /* Bottom Slice */ 5315 /* bottom */ 5316 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 5317 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5318 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 5319 /* middle */ 5320 for (i = 0; i < k-1; ++i) { 5321 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5322 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;} 5323 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 5324 } 5325 /* top */ 5326 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 5327 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5328 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 5329 5330 /* Middle Slice */ 5331 for (j = 0; j < k-1; ++j) { 5332 /* bottom */ 5333 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 5334 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; 5335 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 5336 /* middle */ 5337 for (i = 0; i < k-1; ++i) { 5338 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 5339 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; 5340 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 5341 } 5342 /* top */ 5343 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 5344 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; 5345 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 5346 } 5347 5348 /* Top Slice */ 5349 /* bottom */ 5350 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 5351 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5352 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 5353 /* middle */ 5354 for (i = 0; i < k-1; ++i) { 5355 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 5356 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 5357 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 5358 } 5359 /* top */ 5360 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 5361 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5362 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 5363 5364 foffset = offset; 5365 } 5366 break; 5367 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d); 5368 } 5369 } 5370 if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 5371 /* Check permutation */ 5372 { 5373 PetscInt *check; 5374 5375 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 5376 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]);} 5377 for (i = 0; i < size; ++i) check[perm[i]] = i; 5378 for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 5379 ierr = PetscFree(check);CHKERRQ(ierr); 5380 } 5381 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 5382 } 5383 PetscFunctionReturn(0); 5384 } 5385 5386 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5387 { 5388 PetscDS prob; 5389 PetscInt depth, Nf, h; 5390 DMLabel label; 5391 PetscErrorCode ierr; 5392 5393 PetscFunctionBeginHot; 5394 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 5395 Nf = prob->Nf; 5396 label = dm->depthLabel; 5397 *dspace = NULL; 5398 if (field < Nf) { 5399 PetscObject disc = prob->disc[field]; 5400 5401 if (disc->classid == PETSCFE_CLASSID) { 5402 PetscDualSpace dsp; 5403 5404 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 5405 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 5406 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 5407 h = depth - 1 - h; 5408 if (h) { 5409 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 5410 } else { 5411 *dspace = dsp; 5412 } 5413 } 5414 } 5415 PetscFunctionReturn(0); 5416 } 5417 5418 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5419 { 5420 PetscScalar *array, *vArray; 5421 const PetscInt *cone, *coneO; 5422 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5423 PetscErrorCode ierr; 5424 5425 PetscFunctionBeginHot; 5426 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5427 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5428 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5429 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5430 if (!values || !*values) { 5431 if ((point >= pStart) && (point < pEnd)) { 5432 PetscInt dof; 5433 5434 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5435 size += dof; 5436 } 5437 for (p = 0; p < numPoints; ++p) { 5438 const PetscInt cp = cone[p]; 5439 PetscInt dof; 5440 5441 if ((cp < pStart) || (cp >= pEnd)) continue; 5442 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5443 size += dof; 5444 } 5445 if (!values) { 5446 if (csize) *csize = size; 5447 PetscFunctionReturn(0); 5448 } 5449 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 5450 } else { 5451 array = *values; 5452 } 5453 size = 0; 5454 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 5455 if ((point >= pStart) && (point < pEnd)) { 5456 PetscInt dof, off, d; 5457 PetscScalar *varr; 5458 5459 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5460 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5461 varr = &vArray[off]; 5462 for (d = 0; d < dof; ++d, ++offset) { 5463 array[offset] = varr[d]; 5464 } 5465 size += dof; 5466 } 5467 for (p = 0; p < numPoints; ++p) { 5468 const PetscInt cp = cone[p]; 5469 PetscInt o = coneO[p]; 5470 PetscInt dof, off, d; 5471 PetscScalar *varr; 5472 5473 if ((cp < pStart) || (cp >= pEnd)) continue; 5474 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5475 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 5476 varr = &vArray[off]; 5477 if (o >= 0) { 5478 for (d = 0; d < dof; ++d, ++offset) { 5479 array[offset] = varr[d]; 5480 } 5481 } else { 5482 for (d = dof-1; d >= 0; --d, ++offset) { 5483 array[offset] = varr[d]; 5484 } 5485 } 5486 size += dof; 5487 } 5488 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 5489 if (!*values) { 5490 if (csize) *csize = size; 5491 *values = array; 5492 } else { 5493 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5494 *csize = size; 5495 } 5496 PetscFunctionReturn(0); 5497 } 5498 5499 /* Compress out points not in the section */ 5500 PETSC_STATIC_INLINE PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 5501 { 5502 const PetscInt np = *numPoints; 5503 PetscInt pStart, pEnd, p, q; 5504 PetscErrorCode ierr; 5505 5506 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5507 for (p = 0, q = 0; p < np; ++p) { 5508 const PetscInt r = points[p*2]; 5509 if ((r >= pStart) && (r < pEnd)) { 5510 points[q*2] = r; 5511 points[q*2+1] = points[p*2+1]; 5512 ++q; 5513 } 5514 } 5515 *numPoints = q; 5516 return 0; 5517 } 5518 5519 /* Compressed closure does not apply closure permutation */ 5520 PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5521 { 5522 const PetscInt *cla = NULL; 5523 PetscInt np, *pts = NULL; 5524 PetscErrorCode ierr; 5525 5526 PetscFunctionBeginHot; 5527 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 5528 if (*clPoints) { 5529 PetscInt dof, off; 5530 5531 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 5532 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 5533 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 5534 np = dof/2; 5535 pts = (PetscInt *) &cla[off]; 5536 } else { 5537 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 5538 ierr = CompressPoints_Private(section, &np, pts);CHKERRQ(ierr); 5539 } 5540 *numPoints = np; 5541 *points = pts; 5542 *clp = cla; 5543 PetscFunctionReturn(0); 5544 } 5545 5546 PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5547 { 5548 PetscErrorCode ierr; 5549 5550 PetscFunctionBeginHot; 5551 if (!*clPoints) { 5552 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 5553 } else { 5554 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 5555 } 5556 *numPoints = 0; 5557 *points = NULL; 5558 *clSec = NULL; 5559 *clPoints = NULL; 5560 *clp = NULL; 5561 PetscFunctionReturn(0); 5562 } 5563 5564 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[]) 5565 { 5566 PetscInt offset = 0, p; 5567 const PetscInt **perms = NULL; 5568 const PetscScalar **flips = NULL; 5569 PetscErrorCode ierr; 5570 5571 PetscFunctionBeginHot; 5572 *size = 0; 5573 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5574 for (p = 0; p < numPoints; p++) { 5575 const PetscInt point = points[2*p]; 5576 const PetscInt *perm = perms ? perms[p] : NULL; 5577 const PetscScalar *flip = flips ? flips[p] : NULL; 5578 PetscInt dof, off, d; 5579 const PetscScalar *varr; 5580 5581 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5582 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5583 varr = &vArray[off]; 5584 if (clperm) { 5585 if (perm) { 5586 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 5587 } else { 5588 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 5589 } 5590 if (flip) { 5591 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 5592 } 5593 } else { 5594 if (perm) { 5595 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 5596 } else { 5597 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 5598 } 5599 if (flip) { 5600 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 5601 } 5602 } 5603 offset += dof; 5604 } 5605 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5606 *size = offset; 5607 PetscFunctionReturn(0); 5608 } 5609 5610 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[]) 5611 { 5612 PetscInt offset = 0, f; 5613 PetscErrorCode ierr; 5614 5615 PetscFunctionBeginHot; 5616 *size = 0; 5617 for (f = 0; f < numFields; ++f) { 5618 PetscInt p; 5619 const PetscInt **perms = NULL; 5620 const PetscScalar **flips = NULL; 5621 5622 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5623 for (p = 0; p < numPoints; p++) { 5624 const PetscInt point = points[2*p]; 5625 PetscInt fdof, foff, b; 5626 const PetscScalar *varr; 5627 const PetscInt *perm = perms ? perms[p] : NULL; 5628 const PetscScalar *flip = flips ? flips[p] : NULL; 5629 5630 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5631 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5632 varr = &vArray[foff]; 5633 if (clperm) { 5634 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 5635 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 5636 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 5637 } else { 5638 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 5639 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 5640 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 5641 } 5642 offset += fdof; 5643 } 5644 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5645 } 5646 *size = offset; 5647 PetscFunctionReturn(0); 5648 } 5649 5650 /*@C 5651 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5652 5653 Not collective 5654 5655 Input Parameters: 5656 + dm - The DM 5657 . section - The section describing the layout in v, or NULL to use the default section 5658 . v - The local vector 5659 - point - The point in the DM 5660 5661 Input/Output Parameters: 5662 + csize - The size of the input values array, or NULL; on output the number of values in the closure 5663 - values - An array to use for the values, or NULL to have it allocated automatically; 5664 if the user provided NULL, it is a borrowed array and should not be freed 5665 5666 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 5667 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 5668 $ assembly function, and a user may already have allocated storage for this operation. 5669 $ 5670 $ A typical use could be 5671 $ 5672 $ values = NULL; 5673 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5674 $ for (cl = 0; cl < clSize; ++cl) { 5675 $ <Compute on closure> 5676 $ } 5677 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5678 $ 5679 $ or 5680 $ 5681 $ PetscMalloc1(clMaxSize, &values); 5682 $ for (p = pStart; p < pEnd; ++p) { 5683 $ clSize = clMaxSize; 5684 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5685 $ for (cl = 0; cl < clSize; ++cl) { 5686 $ <Compute on closure> 5687 $ } 5688 $ } 5689 $ PetscFree(values); 5690 5691 Fortran Notes: 5692 Since it returns an array, this routine is only available in Fortran 90, and you must 5693 include petsc.h90 in your code. 5694 5695 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5696 5697 Level: intermediate 5698 5699 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5700 @*/ 5701 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5702 { 5703 PetscSection clSection; 5704 IS clPoints; 5705 PetscInt *points = NULL; 5706 const PetscInt *clp, *perm; 5707 PetscInt depth, numFields, numPoints, asize; 5708 PetscErrorCode ierr; 5709 5710 PetscFunctionBeginHot; 5711 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5712 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5713 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5714 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5715 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5716 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5717 if (depth == 1 && numFields < 2) { 5718 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5719 PetscFunctionReturn(0); 5720 } 5721 /* Get points */ 5722 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5723 /* Get sizes */ 5724 asize = 0; 5725 for (PetscInt p = 0; p < numPoints*2; p += 2) { 5726 PetscInt dof; 5727 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5728 asize += dof; 5729 } 5730 if (values) { 5731 const PetscScalar *vArray; 5732 PetscInt size; 5733 5734 if (*values) { 5735 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); 5736 } else {ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, values);CHKERRQ(ierr);} 5737 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm);CHKERRQ(ierr); 5738 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5739 /* Get values */ 5740 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values);CHKERRQ(ierr);} 5741 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values);CHKERRQ(ierr);} 5742 if (PetscUnlikely(asize != size)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size); 5743 /* Cleanup array */ 5744 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5745 } 5746 if (csize) *csize = asize; 5747 /* Cleanup points */ 5748 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5749 PetscFunctionReturn(0); 5750 } 5751 5752 PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5753 { 5754 DMLabel depthLabel; 5755 PetscSection clSection; 5756 IS clPoints; 5757 PetscScalar *array; 5758 const PetscScalar *vArray; 5759 PetscInt *points = NULL; 5760 const PetscInt *clp, *perm = NULL; 5761 PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5762 PetscErrorCode ierr; 5763 5764 PetscFunctionBeginHot; 5765 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5766 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5767 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5768 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5769 ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr); 5770 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 5771 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5772 if (mdepth == 1 && numFields < 2) { 5773 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5774 PetscFunctionReturn(0); 5775 } 5776 /* Get points */ 5777 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5778 for (clsize=0,p=0; p<Np; p++) { 5779 PetscInt dof; 5780 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 5781 clsize += dof; 5782 } 5783 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm);CHKERRQ(ierr); 5784 /* Filter points */ 5785 for (p = 0; p < numPoints*2; p += 2) { 5786 PetscInt dep; 5787 5788 ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr); 5789 if (dep != depth) continue; 5790 points[Np*2+0] = points[p]; 5791 points[Np*2+1] = points[p+1]; 5792 ++Np; 5793 } 5794 /* Get array */ 5795 if (!values || !*values) { 5796 PetscInt asize = 0, dof; 5797 5798 for (p = 0; p < Np*2; p += 2) { 5799 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5800 asize += dof; 5801 } 5802 if (!values) { 5803 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5804 if (csize) *csize = asize; 5805 PetscFunctionReturn(0); 5806 } 5807 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 5808 } else { 5809 array = *values; 5810 } 5811 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5812 /* Get values */ 5813 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 5814 else {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);} 5815 /* Cleanup points */ 5816 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5817 /* Cleanup array */ 5818 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5819 if (!*values) { 5820 if (csize) *csize = size; 5821 *values = array; 5822 } else { 5823 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5824 *csize = size; 5825 } 5826 PetscFunctionReturn(0); 5827 } 5828 5829 /*@C 5830 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5831 5832 Not collective 5833 5834 Input Parameters: 5835 + dm - The DM 5836 . section - The section describing the layout in v, or NULL to use the default section 5837 . v - The local vector 5838 . point - The point in the DM 5839 . csize - The number of values in the closure, or NULL 5840 - values - The array of values, which is a borrowed array and should not be freed 5841 5842 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 5843 5844 Fortran Notes: 5845 Since it returns an array, this routine is only available in Fortran 90, and you must 5846 include petsc.h90 in your code. 5847 5848 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5849 5850 Level: intermediate 5851 5852 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5853 @*/ 5854 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5855 { 5856 PetscInt size = 0; 5857 PetscErrorCode ierr; 5858 5859 PetscFunctionBegin; 5860 /* Should work without recalculating size */ 5861 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 5862 *values = NULL; 5863 PetscFunctionReturn(0); 5864 } 5865 5866 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 5867 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5868 5869 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[]) 5870 { 5871 PetscInt cdof; /* The number of constraints on this point */ 5872 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5873 PetscScalar *a; 5874 PetscInt off, cind = 0, k; 5875 PetscErrorCode ierr; 5876 5877 PetscFunctionBegin; 5878 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5879 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5880 a = &array[off]; 5881 if (!cdof || setBC) { 5882 if (clperm) { 5883 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 5884 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5885 } else { 5886 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 5887 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5888 } 5889 } else { 5890 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5891 if (clperm) { 5892 if (perm) {for (k = 0; k < dof; ++k) { 5893 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5894 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5895 } 5896 } else { 5897 for (k = 0; k < dof; ++k) { 5898 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5899 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5900 } 5901 } 5902 } else { 5903 if (perm) { 5904 for (k = 0; k < dof; ++k) { 5905 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5906 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5907 } 5908 } else { 5909 for (k = 0; k < dof; ++k) { 5910 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5911 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5912 } 5913 } 5914 } 5915 } 5916 PetscFunctionReturn(0); 5917 } 5918 5919 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[]) 5920 { 5921 PetscInt cdof; /* The number of constraints on this point */ 5922 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5923 PetscScalar *a; 5924 PetscInt off, cind = 0, k; 5925 PetscErrorCode ierr; 5926 5927 PetscFunctionBegin; 5928 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5929 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5930 a = &array[off]; 5931 if (cdof) { 5932 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5933 if (clperm) { 5934 if (perm) { 5935 for (k = 0; k < dof; ++k) { 5936 if ((cind < cdof) && (k == cdofs[cind])) { 5937 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5938 cind++; 5939 } 5940 } 5941 } else { 5942 for (k = 0; k < dof; ++k) { 5943 if ((cind < cdof) && (k == cdofs[cind])) { 5944 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5945 cind++; 5946 } 5947 } 5948 } 5949 } else { 5950 if (perm) { 5951 for (k = 0; k < dof; ++k) { 5952 if ((cind < cdof) && (k == cdofs[cind])) { 5953 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5954 cind++; 5955 } 5956 } 5957 } else { 5958 for (k = 0; k < dof; ++k) { 5959 if ((cind < cdof) && (k == cdofs[cind])) { 5960 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5961 cind++; 5962 } 5963 } 5964 } 5965 } 5966 } 5967 PetscFunctionReturn(0); 5968 } 5969 5970 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[]) 5971 { 5972 PetscScalar *a; 5973 PetscInt fdof, foff, fcdof, foffset = *offset; 5974 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5975 PetscInt cind = 0, b; 5976 PetscErrorCode ierr; 5977 5978 PetscFunctionBegin; 5979 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5980 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 5981 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5982 a = &array[foff]; 5983 if (!fcdof || setBC) { 5984 if (clperm) { 5985 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 5986 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 5987 } else { 5988 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 5989 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 5990 } 5991 } else { 5992 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5993 if (clperm) { 5994 if (perm) { 5995 for (b = 0; b < fdof; b++) { 5996 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5997 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 5998 } 5999 } else { 6000 for (b = 0; b < fdof; b++) { 6001 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6002 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6003 } 6004 } 6005 } else { 6006 if (perm) { 6007 for (b = 0; b < fdof; b++) { 6008 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6009 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])) {++cind; continue;} 6014 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6015 } 6016 } 6017 } 6018 } 6019 *offset += fdof; 6020 PetscFunctionReturn(0); 6021 } 6022 6023 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[]) 6024 { 6025 PetscScalar *a; 6026 PetscInt fdof, foff, fcdof, foffset = *offset; 6027 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6028 PetscInt Nc, cind = 0, ncind = 0, b; 6029 PetscBool ncSet, fcSet; 6030 PetscErrorCode ierr; 6031 6032 PetscFunctionBegin; 6033 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 6034 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6035 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6036 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 6037 a = &array[foff]; 6038 if (fcdof) { 6039 /* We just override fcdof and fcdofs with Ncc and comps */ 6040 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6041 if (clperm) { 6042 if (perm) { 6043 if (comps) { 6044 for (b = 0; b < fdof; b++) { 6045 ncSet = fcSet = PETSC_FALSE; 6046 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6047 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6048 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 6049 } 6050 } else { 6051 for (b = 0; b < fdof; b++) { 6052 if ((cind < fcdof) && (b == fcdofs[cind])) { 6053 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6054 ++cind; 6055 } 6056 } 6057 } 6058 } else { 6059 if (comps) { 6060 for (b = 0; b < fdof; b++) { 6061 ncSet = fcSet = PETSC_FALSE; 6062 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6063 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6064 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 6065 } 6066 } else { 6067 for (b = 0; b < fdof; b++) { 6068 if ((cind < fcdof) && (b == fcdofs[cind])) { 6069 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6070 ++cind; 6071 } 6072 } 6073 } 6074 } 6075 } else { 6076 if (perm) { 6077 if (comps) { 6078 for (b = 0; b < fdof; b++) { 6079 ncSet = fcSet = PETSC_FALSE; 6080 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6081 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6082 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 6083 } 6084 } else { 6085 for (b = 0; b < fdof; b++) { 6086 if ((cind < fcdof) && (b == fcdofs[cind])) { 6087 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6088 ++cind; 6089 } 6090 } 6091 } 6092 } else { 6093 if (comps) { 6094 for (b = 0; b < fdof; b++) { 6095 ncSet = fcSet = PETSC_FALSE; 6096 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6097 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6098 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 6099 } 6100 } else { 6101 for (b = 0; b < fdof; b++) { 6102 if ((cind < fcdof) && (b == fcdofs[cind])) { 6103 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6104 ++cind; 6105 } 6106 } 6107 } 6108 } 6109 } 6110 } 6111 *offset += fdof; 6112 PetscFunctionReturn(0); 6113 } 6114 6115 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6116 { 6117 PetscScalar *array; 6118 const PetscInt *cone, *coneO; 6119 PetscInt pStart, pEnd, p, numPoints, off, dof; 6120 PetscErrorCode ierr; 6121 6122 PetscFunctionBeginHot; 6123 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6124 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 6125 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 6126 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 6127 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6128 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6129 const PetscInt cp = !p ? point : cone[p-1]; 6130 const PetscInt o = !p ? 0 : coneO[p-1]; 6131 6132 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 6133 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 6134 /* ADD_VALUES */ 6135 { 6136 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6137 PetscScalar *a; 6138 PetscInt cdof, coff, cind = 0, k; 6139 6140 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 6141 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 6142 a = &array[coff]; 6143 if (!cdof) { 6144 if (o >= 0) { 6145 for (k = 0; k < dof; ++k) { 6146 a[k] += values[off+k]; 6147 } 6148 } else { 6149 for (k = 0; k < dof; ++k) { 6150 a[k] += values[off+dof-k-1]; 6151 } 6152 } 6153 } else { 6154 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 6155 if (o >= 0) { 6156 for (k = 0; k < dof; ++k) { 6157 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6158 a[k] += values[off+k]; 6159 } 6160 } else { 6161 for (k = 0; k < dof; ++k) { 6162 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6163 a[k] += values[off+dof-k-1]; 6164 } 6165 } 6166 } 6167 } 6168 } 6169 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6170 PetscFunctionReturn(0); 6171 } 6172 6173 /*@C 6174 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6175 6176 Not collective 6177 6178 Input Parameters: 6179 + dm - The DM 6180 . section - The section describing the layout in v, or NULL to use the default section 6181 . v - The local vector 6182 . point - The point in the DM 6183 . values - The array of values 6184 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 6185 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 6186 6187 Fortran Notes: 6188 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6189 6190 Level: intermediate 6191 6192 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6193 @*/ 6194 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6195 { 6196 PetscSection clSection; 6197 IS clPoints; 6198 PetscScalar *array; 6199 PetscInt *points = NULL; 6200 const PetscInt *clp, *clperm = NULL; 6201 PetscInt depth, numFields, numPoints, p, clsize; 6202 PetscErrorCode ierr; 6203 6204 PetscFunctionBeginHot; 6205 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6206 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6207 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6208 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6209 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6210 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6211 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 6212 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 6213 PetscFunctionReturn(0); 6214 } 6215 /* Get points */ 6216 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6217 for (clsize=0,p=0; p<numPoints; p++) { 6218 PetscInt dof; 6219 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 6220 clsize += dof; 6221 } 6222 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 6223 /* Get array */ 6224 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6225 /* Get values */ 6226 if (numFields > 0) { 6227 PetscInt offset = 0, f; 6228 for (f = 0; f < numFields; ++f) { 6229 const PetscInt **perms = NULL; 6230 const PetscScalar **flips = NULL; 6231 6232 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6233 switch (mode) { 6234 case INSERT_VALUES: 6235 for (p = 0; p < numPoints; p++) { 6236 const PetscInt point = points[2*p]; 6237 const PetscInt *perm = perms ? perms[p] : NULL; 6238 const PetscScalar *flip = flips ? flips[p] : NULL; 6239 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6240 } break; 6241 case INSERT_ALL_VALUES: 6242 for (p = 0; p < numPoints; p++) { 6243 const PetscInt point = points[2*p]; 6244 const PetscInt *perm = perms ? perms[p] : NULL; 6245 const PetscScalar *flip = flips ? flips[p] : NULL; 6246 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6247 } break; 6248 case INSERT_BC_VALUES: 6249 for (p = 0; p < numPoints; p++) { 6250 const PetscInt point = points[2*p]; 6251 const PetscInt *perm = perms ? perms[p] : NULL; 6252 const PetscScalar *flip = flips ? flips[p] : NULL; 6253 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6254 } break; 6255 case ADD_VALUES: 6256 for (p = 0; p < numPoints; p++) { 6257 const PetscInt point = points[2*p]; 6258 const PetscInt *perm = perms ? perms[p] : NULL; 6259 const PetscScalar *flip = flips ? flips[p] : NULL; 6260 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6261 } break; 6262 case ADD_ALL_VALUES: 6263 for (p = 0; p < numPoints; p++) { 6264 const PetscInt point = points[2*p]; 6265 const PetscInt *perm = perms ? perms[p] : NULL; 6266 const PetscScalar *flip = flips ? flips[p] : NULL; 6267 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6268 } break; 6269 case ADD_BC_VALUES: 6270 for (p = 0; p < numPoints; p++) { 6271 const PetscInt point = points[2*p]; 6272 const PetscInt *perm = perms ? perms[p] : NULL; 6273 const PetscScalar *flip = flips ? flips[p] : NULL; 6274 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6275 } break; 6276 default: 6277 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6278 } 6279 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6280 } 6281 } else { 6282 PetscInt dof, off; 6283 const PetscInt **perms = NULL; 6284 const PetscScalar **flips = NULL; 6285 6286 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6287 switch (mode) { 6288 case INSERT_VALUES: 6289 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6290 const PetscInt point = points[2*p]; 6291 const PetscInt *perm = perms ? perms[p] : NULL; 6292 const PetscScalar *flip = flips ? flips[p] : NULL; 6293 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6294 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6295 } break; 6296 case INSERT_ALL_VALUES: 6297 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6298 const PetscInt point = points[2*p]; 6299 const PetscInt *perm = perms ? perms[p] : NULL; 6300 const PetscScalar *flip = flips ? flips[p] : NULL; 6301 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6302 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6303 } break; 6304 case INSERT_BC_VALUES: 6305 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6306 const PetscInt point = points[2*p]; 6307 const PetscInt *perm = perms ? perms[p] : NULL; 6308 const PetscScalar *flip = flips ? flips[p] : NULL; 6309 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6310 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6311 } break; 6312 case ADD_VALUES: 6313 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6314 const PetscInt point = points[2*p]; 6315 const PetscInt *perm = perms ? perms[p] : NULL; 6316 const PetscScalar *flip = flips ? flips[p] : NULL; 6317 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6318 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6319 } break; 6320 case ADD_ALL_VALUES: 6321 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6322 const PetscInt point = points[2*p]; 6323 const PetscInt *perm = perms ? perms[p] : NULL; 6324 const PetscScalar *flip = flips ? flips[p] : NULL; 6325 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6326 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6327 } break; 6328 case ADD_BC_VALUES: 6329 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6330 const PetscInt point = points[2*p]; 6331 const PetscInt *perm = perms ? perms[p] : NULL; 6332 const PetscScalar *flip = flips ? flips[p] : NULL; 6333 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6334 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6335 } break; 6336 default: 6337 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6338 } 6339 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6340 } 6341 /* Cleanup points */ 6342 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6343 /* Cleanup array */ 6344 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6345 PetscFunctionReturn(0); 6346 } 6347 6348 /* Check whether the given point is in the label. If not, update the offset to skip this point */ 6349 PETSC_STATIC_INLINE PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 6350 { 6351 PetscFunctionBegin; 6352 if (label) { 6353 PetscInt val, fdof; 6354 PetscErrorCode ierr; 6355 6356 /* There is a problem with this: 6357 Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that 6358 touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell. 6359 Thus I am only going to check val != -1, not val != labelId 6360 */ 6361 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 6362 if (val < 0) { 6363 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6364 *offset += fdof; 6365 PetscFunctionReturn(1); 6366 } 6367 } 6368 PetscFunctionReturn(0); 6369 } 6370 6371 /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 6372 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) 6373 { 6374 PetscSection clSection; 6375 IS clPoints; 6376 PetscScalar *array; 6377 PetscInt *points = NULL; 6378 const PetscInt *clp; 6379 PetscInt numFields, numPoints, p; 6380 PetscInt offset = 0, f; 6381 PetscErrorCode ierr; 6382 6383 PetscFunctionBeginHot; 6384 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6385 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6386 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6387 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6388 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6389 /* Get points */ 6390 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6391 /* Get array */ 6392 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6393 /* Get values */ 6394 for (f = 0; f < numFields; ++f) { 6395 const PetscInt **perms = NULL; 6396 const PetscScalar **flips = NULL; 6397 6398 if (!fieldActive[f]) { 6399 for (p = 0; p < numPoints*2; p += 2) { 6400 PetscInt fdof; 6401 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6402 offset += fdof; 6403 } 6404 continue; 6405 } 6406 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6407 switch (mode) { 6408 case INSERT_VALUES: 6409 for (p = 0; p < numPoints; p++) { 6410 const PetscInt point = points[2*p]; 6411 const PetscInt *perm = perms ? perms[p] : NULL; 6412 const PetscScalar *flip = flips ? flips[p] : NULL; 6413 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6414 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array); 6415 } break; 6416 case INSERT_ALL_VALUES: 6417 for (p = 0; p < numPoints; p++) { 6418 const PetscInt point = points[2*p]; 6419 const PetscInt *perm = perms ? perms[p] : NULL; 6420 const PetscScalar *flip = flips ? flips[p] : NULL; 6421 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6422 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array); 6423 } break; 6424 case INSERT_BC_VALUES: 6425 for (p = 0; p < numPoints; p++) { 6426 const PetscInt point = points[2*p]; 6427 const PetscInt *perm = perms ? perms[p] : NULL; 6428 const PetscScalar *flip = flips ? flips[p] : NULL; 6429 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6430 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array); 6431 } break; 6432 case ADD_VALUES: 6433 for (p = 0; p < numPoints; p++) { 6434 const PetscInt point = points[2*p]; 6435 const PetscInt *perm = perms ? perms[p] : NULL; 6436 const PetscScalar *flip = flips ? flips[p] : NULL; 6437 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6438 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array); 6439 } break; 6440 case ADD_ALL_VALUES: 6441 for (p = 0; p < numPoints; p++) { 6442 const PetscInt point = points[2*p]; 6443 const PetscInt *perm = perms ? perms[p] : NULL; 6444 const PetscScalar *flip = flips ? flips[p] : NULL; 6445 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6446 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array); 6447 } break; 6448 default: 6449 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6450 } 6451 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6452 } 6453 /* Cleanup points */ 6454 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6455 /* Cleanup array */ 6456 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6457 PetscFunctionReturn(0); 6458 } 6459 6460 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6461 { 6462 PetscMPIInt rank; 6463 PetscInt i, j; 6464 PetscErrorCode ierr; 6465 6466 PetscFunctionBegin; 6467 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr); 6468 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 6469 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 6470 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 6471 numCIndices = numCIndices ? numCIndices : numRIndices; 6472 if (!values) PetscFunctionReturn(0); 6473 for (i = 0; i < numRIndices; i++) { 6474 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 6475 for (j = 0; j < numCIndices; j++) { 6476 #if defined(PETSC_USE_COMPLEX) 6477 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 6478 #else 6479 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 6480 #endif 6481 } 6482 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6483 } 6484 PetscFunctionReturn(0); 6485 } 6486 6487 /* 6488 DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 6489 6490 Input Parameters: 6491 + section - The section for this data layout 6492 . islocal - Is the section (and thus indices being requested) local or global? 6493 . point - The point contributing dofs with these indices 6494 . off - The global offset of this point 6495 . loff - The local offset of each field 6496 . setBC - The flag determining whether to include indices of boundary values 6497 . perm - A permutation of the dofs on this point, or NULL 6498 - indperm - A permutation of the entire indices array, or NULL 6499 6500 Output Parameter: 6501 . indices - Indices for dofs on this point 6502 6503 Level: developer 6504 6505 Note: The indices could be local or global, depending on the value of 'off'. 6506 */ 6507 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6508 { 6509 PetscInt dof; /* The number of unknowns on this point */ 6510 PetscInt cdof; /* The number of constraints on this point */ 6511 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6512 PetscInt cind = 0, k; 6513 PetscErrorCode ierr; 6514 6515 PetscFunctionBegin; 6516 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6517 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6518 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6519 if (!cdof || setBC) { 6520 for (k = 0; k < dof; ++k) { 6521 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6522 const PetscInt ind = indperm ? indperm[preind] : preind; 6523 6524 indices[ind] = off + k; 6525 } 6526 } else { 6527 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6528 for (k = 0; k < dof; ++k) { 6529 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6530 const PetscInt ind = indperm ? indperm[preind] : preind; 6531 6532 if ((cind < cdof) && (k == cdofs[cind])) { 6533 /* Insert check for returning constrained indices */ 6534 indices[ind] = -(off+k+1); 6535 ++cind; 6536 } else { 6537 indices[ind] = off + k - (islocal ? 0 : cind); 6538 } 6539 } 6540 } 6541 *loff += dof; 6542 PetscFunctionReturn(0); 6543 } 6544 6545 /* 6546 DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 6547 6548 Input Parameters: 6549 + section - a section (global or local) 6550 - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 6551 . point - point within section 6552 . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 6553 . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 6554 . setBC - identify constrained (boundary condition) points via involution. 6555 . perms - perms[f][permsoff][:] is a permutation of dofs within each field 6556 . permsoff - offset 6557 - indperm - index permutation 6558 6559 Output Parameter: 6560 . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 6561 . indices - array to hold indices (as defined by section) of each dof associated with point 6562 6563 Notes: 6564 If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 6565 If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 6566 in the local vector. 6567 6568 If section is global and setBC=false, the indices for constrained points are negative (and their value is not 6569 significant). It is invalid to call with a global section and setBC=true. 6570 6571 Developer Note: 6572 The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 6573 in the future, global sections may have fields set, in which case we could pass the global section and obtain the 6574 offset could be obtained from the section instead of passing it explicitly as we do now. 6575 6576 Example: 6577 Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 6578 When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 6579 Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 6580 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. 6581 6582 Level: developer 6583 */ 6584 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[]) 6585 { 6586 PetscInt numFields, foff, f; 6587 PetscErrorCode ierr; 6588 6589 PetscFunctionBegin; 6590 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6591 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6592 for (f = 0, foff = 0; f < numFields; ++f) { 6593 PetscInt fdof, cfdof; 6594 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6595 PetscInt cind = 0, b; 6596 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6597 6598 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6599 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6600 if (!cfdof || setBC) { 6601 for (b = 0; b < fdof; ++b) { 6602 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6603 const PetscInt ind = indperm ? indperm[preind] : preind; 6604 6605 indices[ind] = off+foff+b; 6606 } 6607 } else { 6608 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6609 for (b = 0; b < fdof; ++b) { 6610 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6611 const PetscInt ind = indperm ? indperm[preind] : preind; 6612 6613 if ((cind < cfdof) && (b == fcdofs[cind])) { 6614 indices[ind] = -(off+foff+b+1); 6615 ++cind; 6616 } else { 6617 indices[ind] = off + foff + b - (islocal ? 0 : cind); 6618 } 6619 } 6620 } 6621 foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6622 foffs[f] += fdof; 6623 } 6624 PetscFunctionReturn(0); 6625 } 6626 6627 /* 6628 This version believes the globalSection offsets for each field, rather than just the point offset 6629 6630 . foffs - The offset into 'indices' for each field, since it is segregated by field 6631 6632 Notes: 6633 The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6634 Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 6635 */ 6636 static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 6637 { 6638 PetscInt numFields, foff, f; 6639 PetscErrorCode ierr; 6640 6641 PetscFunctionBegin; 6642 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6643 for (f = 0; f < numFields; ++f) { 6644 PetscInt fdof, cfdof; 6645 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6646 PetscInt cind = 0, b; 6647 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6648 6649 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6650 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6651 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 6652 if (!cfdof) { 6653 for (b = 0; b < fdof; ++b) { 6654 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6655 const PetscInt ind = indperm ? indperm[preind] : preind; 6656 6657 indices[ind] = foff+b; 6658 } 6659 } else { 6660 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6661 for (b = 0; b < fdof; ++b) { 6662 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6663 const PetscInt ind = indperm ? indperm[preind] : preind; 6664 6665 if ((cind < cfdof) && (b == fcdofs[cind])) { 6666 indices[ind] = -(foff+b+1); 6667 ++cind; 6668 } else { 6669 indices[ind] = foff+b-cind; 6670 } 6671 } 6672 } 6673 foffs[f] += fdof; 6674 } 6675 PetscFunctionReturn(0); 6676 } 6677 6678 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) 6679 { 6680 Mat cMat; 6681 PetscSection aSec, cSec; 6682 IS aIS; 6683 PetscInt aStart = -1, aEnd = -1; 6684 const PetscInt *anchors; 6685 PetscInt numFields, f, p, q, newP = 0; 6686 PetscInt newNumPoints = 0, newNumIndices = 0; 6687 PetscInt *newPoints, *indices, *newIndices; 6688 PetscInt maxAnchor, maxDof; 6689 PetscInt newOffsets[32]; 6690 PetscInt *pointMatOffsets[32]; 6691 PetscInt *newPointOffsets[32]; 6692 PetscScalar *pointMat[32]; 6693 PetscScalar *newValues=NULL,*tmpValues; 6694 PetscBool anyConstrained = PETSC_FALSE; 6695 PetscErrorCode ierr; 6696 6697 PetscFunctionBegin; 6698 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6699 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6700 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6701 6702 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6703 /* if there are point-to-point constraints */ 6704 if (aSec) { 6705 ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr); 6706 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6707 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 6708 /* figure out how many points are going to be in the new element matrix 6709 * (we allow double counting, because it's all just going to be summed 6710 * into the global matrix anyway) */ 6711 for (p = 0; p < 2*numPoints; p+=2) { 6712 PetscInt b = points[p]; 6713 PetscInt bDof = 0, bSecDof; 6714 6715 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6716 if (!bSecDof) { 6717 continue; 6718 } 6719 if (b >= aStart && b < aEnd) { 6720 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 6721 } 6722 if (bDof) { 6723 /* this point is constrained */ 6724 /* it is going to be replaced by its anchors */ 6725 PetscInt bOff, q; 6726 6727 anyConstrained = PETSC_TRUE; 6728 newNumPoints += bDof; 6729 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 6730 for (q = 0; q < bDof; q++) { 6731 PetscInt a = anchors[bOff + q]; 6732 PetscInt aDof; 6733 6734 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6735 newNumIndices += aDof; 6736 for (f = 0; f < numFields; ++f) { 6737 PetscInt fDof; 6738 6739 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 6740 newOffsets[f+1] += fDof; 6741 } 6742 } 6743 } 6744 else { 6745 /* this point is not constrained */ 6746 newNumPoints++; 6747 newNumIndices += bSecDof; 6748 for (f = 0; f < numFields; ++f) { 6749 PetscInt fDof; 6750 6751 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6752 newOffsets[f+1] += fDof; 6753 } 6754 } 6755 } 6756 } 6757 if (!anyConstrained) { 6758 if (outNumPoints) *outNumPoints = 0; 6759 if (outNumIndices) *outNumIndices = 0; 6760 if (outPoints) *outPoints = NULL; 6761 if (outValues) *outValues = NULL; 6762 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6763 PetscFunctionReturn(0); 6764 } 6765 6766 if (outNumPoints) *outNumPoints = newNumPoints; 6767 if (outNumIndices) *outNumIndices = newNumIndices; 6768 6769 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6770 6771 if (!outPoints && !outValues) { 6772 if (offsets) { 6773 for (f = 0; f <= numFields; f++) { 6774 offsets[f] = newOffsets[f]; 6775 } 6776 } 6777 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6778 PetscFunctionReturn(0); 6779 } 6780 6781 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 6782 6783 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 6784 6785 /* workspaces */ 6786 if (numFields) { 6787 for (f = 0; f < numFields; f++) { 6788 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 6789 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6790 } 6791 } 6792 else { 6793 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 6794 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6795 } 6796 6797 /* get workspaces for the point-to-point matrices */ 6798 if (numFields) { 6799 PetscInt totalOffset, totalMatOffset; 6800 6801 for (p = 0; p < numPoints; p++) { 6802 PetscInt b = points[2*p]; 6803 PetscInt bDof = 0, bSecDof; 6804 6805 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6806 if (!bSecDof) { 6807 for (f = 0; f < numFields; f++) { 6808 newPointOffsets[f][p + 1] = 0; 6809 pointMatOffsets[f][p + 1] = 0; 6810 } 6811 continue; 6812 } 6813 if (b >= aStart && b < aEnd) { 6814 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6815 } 6816 if (bDof) { 6817 for (f = 0; f < numFields; f++) { 6818 PetscInt fDof, q, bOff, allFDof = 0; 6819 6820 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6821 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6822 for (q = 0; q < bDof; q++) { 6823 PetscInt a = anchors[bOff + q]; 6824 PetscInt aFDof; 6825 6826 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 6827 allFDof += aFDof; 6828 } 6829 newPointOffsets[f][p+1] = allFDof; 6830 pointMatOffsets[f][p+1] = fDof * allFDof; 6831 } 6832 } 6833 else { 6834 for (f = 0; f < numFields; f++) { 6835 PetscInt fDof; 6836 6837 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6838 newPointOffsets[f][p+1] = fDof; 6839 pointMatOffsets[f][p+1] = 0; 6840 } 6841 } 6842 } 6843 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 6844 newPointOffsets[f][0] = totalOffset; 6845 pointMatOffsets[f][0] = totalMatOffset; 6846 for (p = 0; p < numPoints; p++) { 6847 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6848 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6849 } 6850 totalOffset = newPointOffsets[f][numPoints]; 6851 totalMatOffset = pointMatOffsets[f][numPoints]; 6852 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 6853 } 6854 } 6855 else { 6856 for (p = 0; p < numPoints; p++) { 6857 PetscInt b = points[2*p]; 6858 PetscInt bDof = 0, bSecDof; 6859 6860 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6861 if (!bSecDof) { 6862 newPointOffsets[0][p + 1] = 0; 6863 pointMatOffsets[0][p + 1] = 0; 6864 continue; 6865 } 6866 if (b >= aStart && b < aEnd) { 6867 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6868 } 6869 if (bDof) { 6870 PetscInt bOff, q, allDof = 0; 6871 6872 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6873 for (q = 0; q < bDof; q++) { 6874 PetscInt a = anchors[bOff + q], aDof; 6875 6876 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 6877 allDof += aDof; 6878 } 6879 newPointOffsets[0][p+1] = allDof; 6880 pointMatOffsets[0][p+1] = bSecDof * allDof; 6881 } 6882 else { 6883 newPointOffsets[0][p+1] = bSecDof; 6884 pointMatOffsets[0][p+1] = 0; 6885 } 6886 } 6887 newPointOffsets[0][0] = 0; 6888 pointMatOffsets[0][0] = 0; 6889 for (p = 0; p < numPoints; p++) { 6890 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6891 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6892 } 6893 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 6894 } 6895 6896 /* output arrays */ 6897 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6898 6899 /* get the point-to-point matrices; construct newPoints */ 6900 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 6901 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6902 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 6903 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 6904 if (numFields) { 6905 for (p = 0, newP = 0; p < numPoints; p++) { 6906 PetscInt b = points[2*p]; 6907 PetscInt o = points[2*p+1]; 6908 PetscInt bDof = 0, bSecDof; 6909 6910 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6911 if (!bSecDof) { 6912 continue; 6913 } 6914 if (b >= aStart && b < aEnd) { 6915 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6916 } 6917 if (bDof) { 6918 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6919 6920 fStart[0] = 0; 6921 fEnd[0] = 0; 6922 for (f = 0; f < numFields; f++) { 6923 PetscInt fDof; 6924 6925 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 6926 fStart[f+1] = fStart[f] + fDof; 6927 fEnd[f+1] = fStart[f+1]; 6928 } 6929 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6930 ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 6931 6932 fAnchorStart[0] = 0; 6933 fAnchorEnd[0] = 0; 6934 for (f = 0; f < numFields; f++) { 6935 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 6936 6937 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 6938 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 6939 } 6940 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6941 for (q = 0; q < bDof; q++) { 6942 PetscInt a = anchors[bOff + q], aOff; 6943 6944 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6945 newPoints[2*(newP + q)] = a; 6946 newPoints[2*(newP + q) + 1] = 0; 6947 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 6948 ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 6949 } 6950 newP += bDof; 6951 6952 if (outValues) { 6953 /* get the point-to-point submatrix */ 6954 for (f = 0; f < numFields; f++) { 6955 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 6956 } 6957 } 6958 } 6959 else { 6960 newPoints[2 * newP] = b; 6961 newPoints[2 * newP + 1] = o; 6962 newP++; 6963 } 6964 } 6965 } else { 6966 for (p = 0; p < numPoints; p++) { 6967 PetscInt b = points[2*p]; 6968 PetscInt o = points[2*p+1]; 6969 PetscInt bDof = 0, bSecDof; 6970 6971 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6972 if (!bSecDof) { 6973 continue; 6974 } 6975 if (b >= aStart && b < aEnd) { 6976 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6977 } 6978 if (bDof) { 6979 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 6980 6981 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6982 ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 6983 6984 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 6985 for (q = 0; q < bDof; q++) { 6986 PetscInt a = anchors[bOff + q], aOff; 6987 6988 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6989 6990 newPoints[2*(newP + q)] = a; 6991 newPoints[2*(newP + q) + 1] = 0; 6992 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 6993 ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 6994 } 6995 newP += bDof; 6996 6997 /* get the point-to-point submatrix */ 6998 if (outValues) { 6999 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 7000 } 7001 } 7002 else { 7003 newPoints[2 * newP] = b; 7004 newPoints[2 * newP + 1] = o; 7005 newP++; 7006 } 7007 } 7008 } 7009 7010 if (outValues) { 7011 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7012 ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr); 7013 /* multiply constraints on the right */ 7014 if (numFields) { 7015 for (f = 0; f < numFields; f++) { 7016 PetscInt oldOff = offsets[f]; 7017 7018 for (p = 0; p < numPoints; p++) { 7019 PetscInt cStart = newPointOffsets[f][p]; 7020 PetscInt b = points[2 * p]; 7021 PetscInt c, r, k; 7022 PetscInt dof; 7023 7024 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7025 if (!dof) { 7026 continue; 7027 } 7028 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7029 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 7030 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7031 7032 for (r = 0; r < numIndices; r++) { 7033 for (c = 0; c < nCols; c++) { 7034 for (k = 0; k < dof; k++) { 7035 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7036 } 7037 } 7038 } 7039 } 7040 else { 7041 /* copy this column as is */ 7042 for (r = 0; r < numIndices; r++) { 7043 for (c = 0; c < dof; c++) { 7044 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7045 } 7046 } 7047 } 7048 oldOff += dof; 7049 } 7050 } 7051 } 7052 else { 7053 PetscInt oldOff = 0; 7054 for (p = 0; p < numPoints; p++) { 7055 PetscInt cStart = newPointOffsets[0][p]; 7056 PetscInt b = points[2 * p]; 7057 PetscInt c, r, k; 7058 PetscInt dof; 7059 7060 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7061 if (!dof) { 7062 continue; 7063 } 7064 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7065 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 7066 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7067 7068 for (r = 0; r < numIndices; r++) { 7069 for (c = 0; c < nCols; c++) { 7070 for (k = 0; k < dof; k++) { 7071 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7072 } 7073 } 7074 } 7075 } 7076 else { 7077 /* copy this column as is */ 7078 for (r = 0; r < numIndices; r++) { 7079 for (c = 0; c < dof; c++) { 7080 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7081 } 7082 } 7083 } 7084 oldOff += dof; 7085 } 7086 } 7087 7088 if (multiplyLeft) { 7089 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 7090 ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr); 7091 /* multiply constraints transpose on the left */ 7092 if (numFields) { 7093 for (f = 0; f < numFields; f++) { 7094 PetscInt oldOff = offsets[f]; 7095 7096 for (p = 0; p < numPoints; p++) { 7097 PetscInt rStart = newPointOffsets[f][p]; 7098 PetscInt b = points[2 * p]; 7099 PetscInt c, r, k; 7100 PetscInt dof; 7101 7102 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7103 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7104 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 7105 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7106 7107 for (r = 0; r < nRows; r++) { 7108 for (c = 0; c < newNumIndices; c++) { 7109 for (k = 0; k < dof; k++) { 7110 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7111 } 7112 } 7113 } 7114 } 7115 else { 7116 /* copy this row as is */ 7117 for (r = 0; r < dof; r++) { 7118 for (c = 0; c < newNumIndices; c++) { 7119 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7120 } 7121 } 7122 } 7123 oldOff += dof; 7124 } 7125 } 7126 } 7127 else { 7128 PetscInt oldOff = 0; 7129 7130 for (p = 0; p < numPoints; p++) { 7131 PetscInt rStart = newPointOffsets[0][p]; 7132 PetscInt b = points[2 * p]; 7133 PetscInt c, r, k; 7134 PetscInt dof; 7135 7136 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7137 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7138 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 7139 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7140 7141 for (r = 0; r < nRows; r++) { 7142 for (c = 0; c < newNumIndices; c++) { 7143 for (k = 0; k < dof; k++) { 7144 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7145 } 7146 } 7147 } 7148 } 7149 else { 7150 /* copy this row as is */ 7151 for (r = 0; r < dof; r++) { 7152 for (c = 0; c < newNumIndices; c++) { 7153 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7154 } 7155 } 7156 } 7157 oldOff += dof; 7158 } 7159 } 7160 7161 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7162 } 7163 else { 7164 newValues = tmpValues; 7165 } 7166 } 7167 7168 /* clean up */ 7169 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 7170 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 7171 7172 if (numFields) { 7173 for (f = 0; f < numFields; f++) { 7174 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 7175 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 7176 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 7177 } 7178 } 7179 else { 7180 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 7181 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 7182 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 7183 } 7184 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7185 7186 /* output */ 7187 if (outPoints) { 7188 *outPoints = newPoints; 7189 } 7190 else { 7191 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 7192 } 7193 if (outValues) { 7194 *outValues = newValues; 7195 } 7196 for (f = 0; f <= numFields; f++) { 7197 offsets[f] = newOffsets[f]; 7198 } 7199 PetscFunctionReturn(0); 7200 } 7201 7202 /*@C 7203 DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 7204 7205 Not collective 7206 7207 Input Parameters: 7208 + dm - The DM 7209 . section - The PetscSection describing the points (a local section) 7210 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7211 . point - The point defining the closure 7212 - useClPerm - Use the closure point permutation if available 7213 7214 Output Parameters: 7215 + numIndices - The number of dof indices in the closure of point with the input sections 7216 . indices - The dof indices 7217 . outOffsets - Array to write the field offsets into, or NULL 7218 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7219 7220 Notes: 7221 Must call DMPlexRestoreClosureIndices() to free allocated memory 7222 7223 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7224 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7225 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7226 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7227 indices (with the above semantics) are implied. 7228 7229 Level: advanced 7230 7231 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7232 @*/ 7233 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7234 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7235 { 7236 /* Closure ordering */ 7237 PetscSection clSection; 7238 IS clPoints; 7239 const PetscInt *clp; 7240 PetscInt *points; 7241 const PetscInt *clperm = NULL; 7242 /* Dof permutation and sign flips */ 7243 const PetscInt **perms[32] = {NULL}; 7244 const PetscScalar **flips[32] = {NULL}; 7245 PetscScalar *valCopy = NULL; 7246 /* Hanging node constraints */ 7247 PetscInt *pointsC = NULL; 7248 PetscScalar *valuesC = NULL; 7249 PetscInt NclC, NiC; 7250 7251 PetscInt *idx; 7252 PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 7253 PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 7254 PetscErrorCode ierr; 7255 7256 PetscFunctionBeginHot; 7257 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7258 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7259 PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7260 if (numIndices) PetscValidPointer(numIndices, 6); 7261 if (indices) PetscValidPointer(indices, 7); 7262 if (outOffsets) PetscValidPointer(outOffsets, 8); 7263 if (values) PetscValidPointer(values, 9); 7264 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 7265 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 7266 ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 7267 /* 1) Get points in closure */ 7268 ierr = DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7269 if (useClPerm) { 7270 PetscInt depth, clsize; 7271 ierr = DMPlexGetPointDepth(dm, point, &depth);CHKERRQ(ierr); 7272 for (clsize=0,p=0; p<Ncl; p++) { 7273 PetscInt dof; 7274 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 7275 clsize += dof; 7276 } 7277 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 7278 } 7279 /* 2) Get number of indices on these points and field offsets from section */ 7280 for (p = 0; p < Ncl*2; p += 2) { 7281 PetscInt dof, fdof; 7282 7283 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7284 for (f = 0; f < Nf; ++f) { 7285 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7286 offsets[f+1] += fdof; 7287 } 7288 Ni += dof; 7289 } 7290 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 7291 if (Nf && offsets[Nf] != Ni) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni); 7292 /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 7293 for (f = 0; f < PetscMax(1, Nf); ++f) { 7294 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7295 else {ierr = PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7296 /* may need to apply sign changes to the element matrix */ 7297 if (values && flips[f]) { 7298 PetscInt foffset = offsets[f]; 7299 7300 for (p = 0; p < Ncl; ++p) { 7301 PetscInt pnt = points[2*p], fdof; 7302 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 7303 7304 if (!Nf) {ierr = PetscSectionGetDof(section, pnt, &fdof);CHKERRQ(ierr);} 7305 else {ierr = PetscSectionGetFieldDof(section, pnt, f, &fdof);CHKERRQ(ierr);} 7306 if (flip) { 7307 PetscInt i, j, k; 7308 7309 if (!valCopy) { 7310 ierr = DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr); 7311 for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 7312 *values = valCopy; 7313 } 7314 for (i = 0; i < fdof; ++i) { 7315 PetscScalar fval = flip[i]; 7316 7317 for (k = 0; k < Ni; ++k) { 7318 valCopy[Ni * (foffset + i) + k] *= fval; 7319 valCopy[Ni * k + (foffset + i)] *= fval; 7320 } 7321 } 7322 } 7323 foffset += fdof; 7324 } 7325 } 7326 } 7327 /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 7328 ierr = DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 7329 if (NclC) { 7330 if (valCopy) {ierr = DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);} 7331 for (f = 0; f < PetscMax(1, Nf); ++f) { 7332 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7333 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7334 } 7335 for (f = 0; f < PetscMax(1, Nf); ++f) { 7336 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7337 else {ierr = PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7338 } 7339 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7340 Ncl = NclC; 7341 Ni = NiC; 7342 points = pointsC; 7343 if (values) *values = valuesC; 7344 } 7345 /* 5) Calculate indices */ 7346 ierr = DMGetWorkArray(dm, Ni, MPIU_INT, &idx);CHKERRQ(ierr); 7347 if (Nf) { 7348 PetscInt idxOff; 7349 PetscBool useFieldOffsets; 7350 7351 if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 7352 ierr = PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets);CHKERRQ(ierr); 7353 if (useFieldOffsets) { 7354 for (p = 0; p < Ncl; ++p) { 7355 const PetscInt pnt = points[p*2]; 7356 7357 ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx);CHKERRQ(ierr); 7358 } 7359 } else { 7360 for (p = 0; p < Ncl; ++p) { 7361 const PetscInt pnt = points[p*2]; 7362 7363 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7364 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7365 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 7366 * global section. */ 7367 ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx);CHKERRQ(ierr); 7368 } 7369 } 7370 } else { 7371 PetscInt off = 0, idxOff; 7372 7373 for (p = 0; p < Ncl; ++p) { 7374 const PetscInt pnt = points[p*2]; 7375 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 7376 7377 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7378 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7379 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 7380 ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx);CHKERRQ(ierr); 7381 } 7382 } 7383 /* 6) Cleanup */ 7384 for (f = 0; f < PetscMax(1, Nf); ++f) { 7385 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7386 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7387 } 7388 if (NclC) { 7389 ierr = DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC);CHKERRQ(ierr); 7390 } else { 7391 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7392 } 7393 7394 if (numIndices) *numIndices = Ni; 7395 if (indices) *indices = idx; 7396 PetscFunctionReturn(0); 7397 } 7398 7399 /*@C 7400 DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 7401 7402 Not collective 7403 7404 Input Parameters: 7405 + dm - The DM 7406 . section - The PetscSection describing the points (a local section) 7407 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7408 . point - The point defining the closure 7409 - useClPerm - Use the closure point permutation if available 7410 7411 Output Parameters: 7412 + numIndices - The number of dof indices in the closure of point with the input sections 7413 . indices - The dof indices 7414 . outOffsets - Array to write the field offsets into, or NULL 7415 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7416 7417 Notes: 7418 If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 7419 7420 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7421 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7422 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7423 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7424 indices (with the above semantics) are implied. 7425 7426 Level: advanced 7427 7428 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7429 @*/ 7430 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7431 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7432 { 7433 PetscErrorCode ierr; 7434 7435 PetscFunctionBegin; 7436 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7437 PetscValidPointer(indices, 7); 7438 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 7439 PetscFunctionReturn(0); 7440 } 7441 7442 /*@C 7443 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 7444 7445 Not collective 7446 7447 Input Parameters: 7448 + dm - The DM 7449 . section - The section describing the layout in v, or NULL to use the default section 7450 . globalSection - The section describing the layout in v, or NULL to use the default global section 7451 . A - The matrix 7452 . point - The point in the DM 7453 . values - The array of values 7454 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7455 7456 Fortran Notes: 7457 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 7458 7459 Level: intermediate 7460 7461 .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7462 @*/ 7463 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7464 { 7465 DM_Plex *mesh = (DM_Plex*) dm->data; 7466 PetscInt *indices; 7467 PetscInt numIndices; 7468 const PetscScalar *valuesOrig = values; 7469 PetscErrorCode ierr; 7470 7471 PetscFunctionBegin; 7472 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7473 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 7474 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7475 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 7476 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 7477 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7478 7479 ierr = DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7480 7481 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 7482 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7483 if (ierr) { 7484 PetscMPIInt rank; 7485 PetscErrorCode ierr2; 7486 7487 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7488 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7489 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 7490 ierr2 = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7491 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7492 CHKERRQ(ierr); 7493 } 7494 if (mesh->printFEM > 1) { 7495 PetscInt i; 7496 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 7497 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 7498 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7499 } 7500 7501 ierr = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7502 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7503 PetscFunctionReturn(0); 7504 } 7505 7506 /*@C 7507 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 7508 7509 Not collective 7510 7511 Input Parameters: 7512 + dmRow - The DM for the row fields 7513 . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 7514 . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 7515 . dmCol - The DM for the column fields 7516 . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 7517 . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 7518 . A - The matrix 7519 . point - The point in the DMs 7520 . values - The array of values 7521 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7522 7523 Level: intermediate 7524 7525 .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7526 @*/ 7527 PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7528 { 7529 DM_Plex *mesh = (DM_Plex*) dmRow->data; 7530 PetscInt *indicesRow, *indicesCol; 7531 PetscInt numIndicesRow, numIndicesCol; 7532 const PetscScalar *valuesOrig = values; 7533 PetscErrorCode ierr; 7534 7535 PetscFunctionBegin; 7536 PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 7537 if (!sectionRow) {ierr = DMGetLocalSection(dmRow, §ionRow);CHKERRQ(ierr);} 7538 PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 7539 if (!globalSectionRow) {ierr = DMGetGlobalSection(dmRow, &globalSectionRow);CHKERRQ(ierr);} 7540 PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 7541 PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 7542 if (!sectionCol) {ierr = DMGetLocalSection(dmCol, §ionCol);CHKERRQ(ierr);} 7543 PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 7544 if (!globalSectionCol) {ierr = DMGetGlobalSection(dmCol, &globalSectionCol);CHKERRQ(ierr);} 7545 PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 7546 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7547 7548 ierr = DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7549 ierr = DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7550 7551 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr);} 7552 ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 7553 if (ierr) { 7554 PetscMPIInt rank; 7555 PetscErrorCode ierr2; 7556 7557 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7558 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7559 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr2); 7560 ierr2 = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7561 ierr2 = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7562 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7563 CHKERRQ(ierr); 7564 } 7565 7566 ierr = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7567 ierr = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7568 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7569 PetscFunctionReturn(0); 7570 } 7571 7572 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7573 { 7574 DM_Plex *mesh = (DM_Plex*) dmf->data; 7575 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7576 PetscInt *cpoints = NULL; 7577 PetscInt *findices, *cindices; 7578 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7579 PetscInt foffsets[32], coffsets[32]; 7580 DMPolytopeType ct; 7581 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7582 PetscErrorCode ierr; 7583 7584 PetscFunctionBegin; 7585 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7586 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7587 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7588 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7589 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7590 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7591 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7592 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7593 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7594 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7595 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7596 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7597 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7598 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7599 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7600 /* Column indices */ 7601 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7602 maxFPoints = numCPoints; 7603 /* Compress out points not in the section */ 7604 /* TODO: Squeeze out points with 0 dof as well */ 7605 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7606 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7607 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7608 cpoints[q*2] = cpoints[p]; 7609 cpoints[q*2+1] = cpoints[p+1]; 7610 ++q; 7611 } 7612 } 7613 numCPoints = q; 7614 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7615 PetscInt fdof; 7616 7617 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7618 if (!dof) continue; 7619 for (f = 0; f < numFields; ++f) { 7620 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7621 coffsets[f+1] += fdof; 7622 } 7623 numCIndices += dof; 7624 } 7625 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7626 /* Row indices */ 7627 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7628 { 7629 DMPlexTransform tr; 7630 DMPolytopeType *rct; 7631 PetscInt *rsize, *rcone, *rornt, Nt; 7632 7633 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7634 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7635 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7636 numSubcells = rsize[Nt-1]; 7637 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7638 } 7639 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7640 for (r = 0, q = 0; r < numSubcells; ++r) { 7641 /* TODO Map from coarse to fine cells */ 7642 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7643 /* Compress out points not in the section */ 7644 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7645 for (p = 0; p < numFPoints*2; p += 2) { 7646 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7647 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7648 if (!dof) continue; 7649 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7650 if (s < q) continue; 7651 ftotpoints[q*2] = fpoints[p]; 7652 ftotpoints[q*2+1] = fpoints[p+1]; 7653 ++q; 7654 } 7655 } 7656 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7657 } 7658 numFPoints = q; 7659 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7660 PetscInt fdof; 7661 7662 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7663 if (!dof) continue; 7664 for (f = 0; f < numFields; ++f) { 7665 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7666 foffsets[f+1] += fdof; 7667 } 7668 numFIndices += dof; 7669 } 7670 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7671 7672 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7673 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7674 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7675 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7676 if (numFields) { 7677 const PetscInt **permsF[32] = {NULL}; 7678 const PetscInt **permsC[32] = {NULL}; 7679 7680 for (f = 0; f < numFields; f++) { 7681 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7682 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7683 } 7684 for (p = 0; p < numFPoints; p++) { 7685 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7686 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7687 } 7688 for (p = 0; p < numCPoints; p++) { 7689 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7690 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7691 } 7692 for (f = 0; f < numFields; f++) { 7693 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7694 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7695 } 7696 } else { 7697 const PetscInt **permsF = NULL; 7698 const PetscInt **permsC = NULL; 7699 7700 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7701 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7702 for (p = 0, off = 0; p < numFPoints; p++) { 7703 const PetscInt *perm = permsF ? permsF[p] : NULL; 7704 7705 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7706 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7707 } 7708 for (p = 0, off = 0; p < numCPoints; p++) { 7709 const PetscInt *perm = permsC ? permsC[p] : NULL; 7710 7711 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7712 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7713 } 7714 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7715 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7716 } 7717 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 7718 /* TODO: flips */ 7719 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7720 if (ierr) { 7721 PetscMPIInt rank; 7722 PetscErrorCode ierr2; 7723 7724 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7725 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7726 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 7727 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 7728 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 7729 CHKERRQ(ierr); 7730 } 7731 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7732 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7733 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7734 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7735 PetscFunctionReturn(0); 7736 } 7737 7738 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 7739 { 7740 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7741 PetscInt *cpoints = NULL; 7742 PetscInt foffsets[32], coffsets[32]; 7743 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7744 DMPolytopeType ct; 7745 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7746 PetscErrorCode ierr; 7747 7748 PetscFunctionBegin; 7749 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7750 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7751 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7752 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7753 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7754 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7755 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7756 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7757 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7758 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7759 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7760 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7761 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7762 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7763 /* Column indices */ 7764 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7765 maxFPoints = numCPoints; 7766 /* Compress out points not in the section */ 7767 /* TODO: Squeeze out points with 0 dof as well */ 7768 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7769 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7770 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7771 cpoints[q*2] = cpoints[p]; 7772 cpoints[q*2+1] = cpoints[p+1]; 7773 ++q; 7774 } 7775 } 7776 numCPoints = q; 7777 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7778 PetscInt fdof; 7779 7780 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7781 if (!dof) continue; 7782 for (f = 0; f < numFields; ++f) { 7783 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7784 coffsets[f+1] += fdof; 7785 } 7786 numCIndices += dof; 7787 } 7788 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7789 /* Row indices */ 7790 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7791 { 7792 DMPlexTransform tr; 7793 DMPolytopeType *rct; 7794 PetscInt *rsize, *rcone, *rornt, Nt; 7795 7796 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7797 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7798 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7799 numSubcells = rsize[Nt-1]; 7800 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7801 } 7802 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7803 for (r = 0, q = 0; r < numSubcells; ++r) { 7804 /* TODO Map from coarse to fine cells */ 7805 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7806 /* Compress out points not in the section */ 7807 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7808 for (p = 0; p < numFPoints*2; p += 2) { 7809 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7810 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7811 if (!dof) continue; 7812 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7813 if (s < q) continue; 7814 ftotpoints[q*2] = fpoints[p]; 7815 ftotpoints[q*2+1] = fpoints[p+1]; 7816 ++q; 7817 } 7818 } 7819 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7820 } 7821 numFPoints = q; 7822 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7823 PetscInt fdof; 7824 7825 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7826 if (!dof) continue; 7827 for (f = 0; f < numFields; ++f) { 7828 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7829 foffsets[f+1] += fdof; 7830 } 7831 numFIndices += dof; 7832 } 7833 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7834 7835 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7836 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7837 if (numFields) { 7838 const PetscInt **permsF[32] = {NULL}; 7839 const PetscInt **permsC[32] = {NULL}; 7840 7841 for (f = 0; f < numFields; f++) { 7842 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7843 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7844 } 7845 for (p = 0; p < numFPoints; p++) { 7846 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7847 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7848 } 7849 for (p = 0; p < numCPoints; p++) { 7850 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7851 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7852 } 7853 for (f = 0; f < numFields; f++) { 7854 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7855 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7856 } 7857 } else { 7858 const PetscInt **permsF = NULL; 7859 const PetscInt **permsC = NULL; 7860 7861 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7862 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7863 for (p = 0, off = 0; p < numFPoints; p++) { 7864 const PetscInt *perm = permsF ? permsF[p] : NULL; 7865 7866 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7867 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7868 } 7869 for (p = 0, off = 0; p < numCPoints; p++) { 7870 const PetscInt *perm = permsC ? permsC[p] : NULL; 7871 7872 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7873 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7874 } 7875 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7876 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7877 } 7878 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7879 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7880 PetscFunctionReturn(0); 7881 } 7882 7883 /*@C 7884 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 7885 7886 Input Parameter: 7887 . dm - The DMPlex object 7888 7889 Output Parameter: 7890 . cellHeight - The height of a cell 7891 7892 Level: developer 7893 7894 .seealso DMPlexSetVTKCellHeight() 7895 @*/ 7896 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7897 { 7898 DM_Plex *mesh = (DM_Plex*) dm->data; 7899 7900 PetscFunctionBegin; 7901 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7902 PetscValidPointer(cellHeight, 2); 7903 *cellHeight = mesh->vtkCellHeight; 7904 PetscFunctionReturn(0); 7905 } 7906 7907 /*@C 7908 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 7909 7910 Input Parameters: 7911 + dm - The DMPlex object 7912 - cellHeight - The height of a cell 7913 7914 Level: developer 7915 7916 .seealso DMPlexGetVTKCellHeight() 7917 @*/ 7918 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7919 { 7920 DM_Plex *mesh = (DM_Plex*) dm->data; 7921 7922 PetscFunctionBegin; 7923 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7924 mesh->vtkCellHeight = cellHeight; 7925 PetscFunctionReturn(0); 7926 } 7927 7928 /*@ 7929 DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 7930 7931 Input Parameter: 7932 . dm - The DMPlex object 7933 7934 Output Parameters: 7935 + gcStart - The first ghost cell, or NULL 7936 - gcEnd - The upper bound on ghost cells, or NULL 7937 7938 Level: advanced 7939 7940 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 7941 @*/ 7942 PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 7943 { 7944 DMLabel ctLabel; 7945 PetscErrorCode ierr; 7946 7947 PetscFunctionBegin; 7948 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7949 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 7950 ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr); 7951 PetscFunctionReturn(0); 7952 } 7953 7954 /* We can easily have a form that takes an IS instead */ 7955 PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 7956 { 7957 PetscSection section, globalSection; 7958 PetscInt *numbers, p; 7959 PetscErrorCode ierr; 7960 7961 PetscFunctionBegin; 7962 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7963 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 7964 for (p = pStart; p < pEnd; ++p) { 7965 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 7966 } 7967 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 7968 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7969 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 7970 for (p = pStart; p < pEnd; ++p) { 7971 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 7972 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 7973 else numbers[p-pStart] += shift; 7974 } 7975 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 7976 if (globalSize) { 7977 PetscLayout layout; 7978 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 7979 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 7980 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 7981 } 7982 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7983 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 7984 PetscFunctionReturn(0); 7985 } 7986 7987 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 7988 { 7989 PetscInt cellHeight, cStart, cEnd; 7990 PetscErrorCode ierr; 7991 7992 PetscFunctionBegin; 7993 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 7994 if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 7995 else {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 7996 ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 7997 PetscFunctionReturn(0); 7998 } 7999 8000 /*@ 8001 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 8002 8003 Input Parameter: 8004 . dm - The DMPlex object 8005 8006 Output Parameter: 8007 . globalCellNumbers - Global cell numbers for all cells on this process 8008 8009 Level: developer 8010 8011 .seealso DMPlexGetVertexNumbering() 8012 @*/ 8013 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8014 { 8015 DM_Plex *mesh = (DM_Plex*) dm->data; 8016 PetscErrorCode ierr; 8017 8018 PetscFunctionBegin; 8019 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8020 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 8021 *globalCellNumbers = mesh->globalCellNumbers; 8022 PetscFunctionReturn(0); 8023 } 8024 8025 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8026 { 8027 PetscInt vStart, vEnd; 8028 PetscErrorCode ierr; 8029 8030 PetscFunctionBegin; 8031 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8032 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8033 ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 8034 PetscFunctionReturn(0); 8035 } 8036 8037 /*@ 8038 DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 8039 8040 Input Parameter: 8041 . dm - The DMPlex object 8042 8043 Output Parameter: 8044 . globalVertexNumbers - Global vertex numbers for all vertices on this process 8045 8046 Level: developer 8047 8048 .seealso DMPlexGetCellNumbering() 8049 @*/ 8050 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8051 { 8052 DM_Plex *mesh = (DM_Plex*) dm->data; 8053 PetscErrorCode ierr; 8054 8055 PetscFunctionBegin; 8056 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8057 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 8058 *globalVertexNumbers = mesh->globalVertexNumbers; 8059 PetscFunctionReturn(0); 8060 } 8061 8062 /*@ 8063 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 8064 8065 Input Parameter: 8066 . dm - The DMPlex object 8067 8068 Output Parameter: 8069 . globalPointNumbers - Global numbers for all points on this process 8070 8071 Level: developer 8072 8073 .seealso DMPlexGetCellNumbering() 8074 @*/ 8075 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8076 { 8077 IS nums[4]; 8078 PetscInt depths[4], gdepths[4], starts[4]; 8079 PetscInt depth, d, shift = 0; 8080 PetscErrorCode ierr; 8081 8082 PetscFunctionBegin; 8083 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8084 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8085 /* For unstratified meshes use dim instead of depth */ 8086 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 8087 for (d = 0; d <= depth; ++d) { 8088 PetscInt end; 8089 8090 depths[d] = depth-d; 8091 ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 8092 if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 8093 } 8094 ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 8095 ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 8096 for (d = 0; d <= depth; ++d) { 8097 if (starts[d] >= 0 && depths[d] != gdepths[d]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 8098 } 8099 for (d = 0; d <= depth; ++d) { 8100 PetscInt pStart, pEnd, gsize; 8101 8102 ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 8103 ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 8104 shift += gsize; 8105 } 8106 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 8107 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 8108 PetscFunctionReturn(0); 8109 } 8110 8111 /*@ 8112 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 8113 8114 Input Parameter: 8115 . dm - The DMPlex object 8116 8117 Output Parameter: 8118 . ranks - The rank field 8119 8120 Options Database Keys: 8121 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 8122 8123 Level: intermediate 8124 8125 .seealso: DMView() 8126 @*/ 8127 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8128 { 8129 DM rdm; 8130 PetscFE fe; 8131 PetscScalar *r; 8132 PetscMPIInt rank; 8133 DMPolytopeType ct; 8134 PetscInt dim, cStart, cEnd, c; 8135 PetscBool simplex; 8136 PetscErrorCode ierr; 8137 8138 PetscFunctionBeginUser; 8139 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8140 PetscValidPointer(ranks, 2); 8141 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 8142 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8143 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8144 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8145 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 8146 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 8147 ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 8148 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 8149 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8150 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8151 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8152 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 8153 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 8154 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 8155 for (c = cStart; c < cEnd; ++c) { 8156 PetscScalar *lr; 8157 8158 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 8159 if (lr) *lr = rank; 8160 } 8161 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 8162 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8163 PetscFunctionReturn(0); 8164 } 8165 8166 /*@ 8167 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 8168 8169 Input Parameters: 8170 + dm - The DMPlex 8171 - label - The DMLabel 8172 8173 Output Parameter: 8174 . val - The label value field 8175 8176 Options Database Keys: 8177 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 8178 8179 Level: intermediate 8180 8181 .seealso: DMView() 8182 @*/ 8183 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8184 { 8185 DM rdm; 8186 PetscFE fe; 8187 PetscScalar *v; 8188 PetscInt dim, cStart, cEnd, c; 8189 PetscErrorCode ierr; 8190 8191 PetscFunctionBeginUser; 8192 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8193 PetscValidPointer(label, 2); 8194 PetscValidPointer(val, 3); 8195 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8196 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8197 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 8198 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 8199 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8200 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8201 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8202 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8203 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 8204 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 8205 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 8206 for (c = cStart; c < cEnd; ++c) { 8207 PetscScalar *lv; 8208 PetscInt cval; 8209 8210 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 8211 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 8212 *lv = cval; 8213 } 8214 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 8215 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8216 PetscFunctionReturn(0); 8217 } 8218 8219 /*@ 8220 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8221 8222 Input Parameter: 8223 . dm - The DMPlex object 8224 8225 Notes: 8226 This is a useful diagnostic when creating meshes programmatically. 8227 8228 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8229 8230 Level: developer 8231 8232 .seealso: DMCreate(), DMSetFromOptions() 8233 @*/ 8234 PetscErrorCode DMPlexCheckSymmetry(DM dm) 8235 { 8236 PetscSection coneSection, supportSection; 8237 const PetscInt *cone, *support; 8238 PetscInt coneSize, c, supportSize, s; 8239 PetscInt pStart, pEnd, p, pp, csize, ssize; 8240 PetscBool storagecheck = PETSC_TRUE; 8241 PetscErrorCode ierr; 8242 8243 PetscFunctionBegin; 8244 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8245 ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr); 8246 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 8247 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 8248 /* Check that point p is found in the support of its cone points, and vice versa */ 8249 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8250 for (p = pStart; p < pEnd; ++p) { 8251 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8252 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8253 for (c = 0; c < coneSize; ++c) { 8254 PetscBool dup = PETSC_FALSE; 8255 PetscInt d; 8256 for (d = c-1; d >= 0; --d) { 8257 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 8258 } 8259 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 8260 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 8261 for (s = 0; s < supportSize; ++s) { 8262 if (support[s] == p) break; 8263 } 8264 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 8265 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 8266 for (s = 0; s < coneSize; ++s) { 8267 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 8268 } 8269 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8270 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 8271 for (s = 0; s < supportSize; ++s) { 8272 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 8273 } 8274 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8275 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 8276 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 8277 } 8278 } 8279 ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 8280 if (p != pp) { storagecheck = PETSC_FALSE; continue; } 8281 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 8282 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 8283 for (s = 0; s < supportSize; ++s) { 8284 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 8285 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 8286 for (c = 0; c < coneSize; ++c) { 8287 ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 8288 if (cone[c] != pp) { c = 0; break; } 8289 if (cone[c] == p) break; 8290 } 8291 if (c >= coneSize) { 8292 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 8293 for (c = 0; c < supportSize; ++c) { 8294 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 8295 } 8296 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8297 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 8298 for (c = 0; c < coneSize; ++c) { 8299 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 8300 } 8301 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8302 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 8303 } 8304 } 8305 } 8306 if (storagecheck) { 8307 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 8308 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 8309 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 8310 } 8311 PetscFunctionReturn(0); 8312 } 8313 8314 /* 8315 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. 8316 */ 8317 static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8318 { 8319 DMPolytopeType cct; 8320 PetscInt ptpoints[4]; 8321 const PetscInt *cone, *ccone, *ptcone; 8322 PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8323 PetscErrorCode ierr; 8324 8325 PetscFunctionBegin; 8326 *unsplit = 0; 8327 switch (ct) { 8328 case DM_POLYTOPE_POINT_PRISM_TENSOR: 8329 ptpoints[npt++] = c; 8330 break; 8331 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8332 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8333 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8334 for (cp = 0; cp < coneSize; ++cp) { 8335 ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr); 8336 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8337 } 8338 break; 8339 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8340 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8341 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8342 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8343 for (cp = 0; cp < coneSize; ++cp) { 8344 ierr = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr); 8345 ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr); 8346 for (ccp = 0; ccp < cconeSize; ++ccp) { 8347 ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr); 8348 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8349 PetscInt p; 8350 for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8351 if (p == npt) ptpoints[npt++] = ccone[ccp]; 8352 } 8353 } 8354 } 8355 break; 8356 default: break; 8357 } 8358 for (pt = 0; pt < npt; ++pt) { 8359 ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr); 8360 if (ptcone[0] == ptcone[1]) ++(*unsplit); 8361 } 8362 PetscFunctionReturn(0); 8363 } 8364 8365 /*@ 8366 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8367 8368 Input Parameters: 8369 + dm - The DMPlex object 8370 - cellHeight - Normally 0 8371 8372 Notes: 8373 This is a useful diagnostic when creating meshes programmatically. 8374 Currently applicable only to homogeneous simplex or tensor meshes. 8375 8376 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8377 8378 Level: developer 8379 8380 .seealso: DMCreate(), DMSetFromOptions() 8381 @*/ 8382 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8383 { 8384 DMPlexInterpolatedFlag interp; 8385 DMPolytopeType ct; 8386 PetscInt vStart, vEnd, cStart, cEnd, c; 8387 PetscErrorCode ierr; 8388 8389 PetscFunctionBegin; 8390 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8391 ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr); 8392 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8393 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8394 for (c = cStart; c < cEnd; ++c) { 8395 PetscInt *closure = NULL; 8396 PetscInt coneSize, closureSize, cl, Nv = 0; 8397 8398 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8399 if ((PetscInt) ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c); 8400 if (ct == DM_POLYTOPE_UNKNOWN) continue; 8401 if (interp == DMPLEX_INTERPOLATED_FULL) { 8402 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8403 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)); 8404 } 8405 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8406 for (cl = 0; cl < closureSize*2; cl += 2) { 8407 const PetscInt p = closure[cl]; 8408 if ((p >= vStart) && (p < vEnd)) ++Nv; 8409 } 8410 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8411 /* Special Case: Tensor faces with identified vertices */ 8412 if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8413 PetscInt unsplit; 8414 8415 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8416 if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 8417 } 8418 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)); 8419 } 8420 PetscFunctionReturn(0); 8421 } 8422 8423 /*@ 8424 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 8425 8426 Not Collective 8427 8428 Input Parameters: 8429 + dm - The DMPlex object 8430 - cellHeight - Normally 0 8431 8432 Notes: 8433 This is a useful diagnostic when creating meshes programmatically. 8434 This routine is only relevant for meshes that are fully interpolated across all ranks. 8435 It will error out if a partially interpolated mesh is given on some rank. 8436 It will do nothing for locally uninterpolated mesh (as there is nothing to check). 8437 8438 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8439 8440 Level: developer 8441 8442 .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 8443 @*/ 8444 PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 8445 { 8446 PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8447 PetscErrorCode ierr; 8448 DMPlexInterpolatedFlag interpEnum; 8449 8450 PetscFunctionBegin; 8451 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8452 ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr); 8453 if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 8454 if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 8455 PetscMPIInt rank; 8456 MPI_Comm comm; 8457 8458 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8459 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8460 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 8461 } 8462 8463 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8464 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8465 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8466 for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 8467 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 8468 for (c = cStart; c < cEnd; ++c) { 8469 const PetscInt *cone, *ornt, *faceSizes, *faces; 8470 const DMPolytopeType *faceTypes; 8471 DMPolytopeType ct; 8472 PetscInt numFaces, coneSize, f; 8473 PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 8474 8475 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8476 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8477 if (unsplit) continue; 8478 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8479 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8480 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 8481 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8482 for (cl = 0; cl < closureSize*2; cl += 2) { 8483 const PetscInt p = closure[cl]; 8484 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 8485 } 8486 ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8487 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); 8488 for (f = 0; f < numFaces; ++f) { 8489 DMPolytopeType fct; 8490 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 8491 8492 ierr = DMPlexGetCellType(dm, cone[f], &fct);CHKERRQ(ierr); 8493 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8494 for (cl = 0; cl < fclosureSize*2; cl += 2) { 8495 const PetscInt p = fclosure[cl]; 8496 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 8497 } 8498 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]); 8499 for (v = 0; v < fnumCorners; ++v) { 8500 if (fclosure[v] != faces[fOff+v]) { 8501 PetscInt v1; 8502 8503 ierr = PetscPrintf(PETSC_COMM_SELF, "face closure:");CHKERRQ(ierr); 8504 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", fclosure[v1]);CHKERRQ(ierr);} 8505 ierr = PetscPrintf(PETSC_COMM_SELF, "\ncell face:");CHKERRQ(ierr); 8506 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", faces[fOff+v1]);CHKERRQ(ierr);} 8507 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8508 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]); 8509 } 8510 } 8511 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8512 fOff += faceSizes[f]; 8513 } 8514 ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8515 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8516 } 8517 } 8518 PetscFunctionReturn(0); 8519 } 8520 8521 /*@ 8522 DMPlexCheckGeometry - Check the geometry of mesh cells 8523 8524 Input Parameter: 8525 . dm - The DMPlex object 8526 8527 Notes: 8528 This is a useful diagnostic when creating meshes programmatically. 8529 8530 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8531 8532 Level: developer 8533 8534 .seealso: DMCreate(), DMSetFromOptions() 8535 @*/ 8536 PetscErrorCode DMPlexCheckGeometry(DM dm) 8537 { 8538 Vec coordinates; 8539 PetscReal detJ, J[9], refVol = 1.0; 8540 PetscReal vol; 8541 PetscBool periodic; 8542 PetscInt dim, depth, dE, d, cStart, cEnd, c; 8543 PetscErrorCode ierr; 8544 8545 PetscFunctionBegin; 8546 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8547 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 8548 if (dim != dE) PetscFunctionReturn(0); 8549 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8550 ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr); 8551 for (d = 0; d < dim; ++d) refVol *= 2.0; 8552 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8553 /* Make sure local coordinates are created, because that step is collective */ 8554 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8555 for (c = cStart; c < cEnd; ++c) { 8556 DMPolytopeType ct; 8557 PetscInt unsplit; 8558 PetscBool ignoreZeroVol = PETSC_FALSE; 8559 8560 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8561 switch (ct) { 8562 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8563 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8564 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8565 ignoreZeroVol = PETSC_TRUE; break; 8566 default: break; 8567 } 8568 switch (ct) { 8569 case DM_POLYTOPE_TRI_PRISM: 8570 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8571 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8572 case DM_POLYTOPE_PYRAMID: 8573 continue; 8574 default: break; 8575 } 8576 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8577 if (unsplit) continue; 8578 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 8579 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); 8580 ierr = PetscInfo2(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 8581 if (depth > 1 && !periodic) { 8582 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 8583 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); 8584 ierr = PetscInfo2(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 8585 } 8586 } 8587 PetscFunctionReturn(0); 8588 } 8589 8590 /*@ 8591 DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 8592 8593 Input Parameters: 8594 . dm - The DMPlex object 8595 8596 Notes: 8597 This is mainly intended for debugging/testing purposes. 8598 It currently checks only meshes with no partition overlapping. 8599 8600 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8601 8602 Level: developer 8603 8604 .seealso: DMGetPointSF(), DMSetFromOptions() 8605 @*/ 8606 PetscErrorCode DMPlexCheckPointSF(DM dm) 8607 { 8608 PetscSF pointSF; 8609 PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 8610 const PetscInt *locals, *rootdegree; 8611 PetscBool distributed; 8612 PetscErrorCode ierr; 8613 8614 PetscFunctionBegin; 8615 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8616 ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr); 8617 ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 8618 if (!distributed) PetscFunctionReturn(0); 8619 ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 8620 if (overlap) { 8621 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping");CHKERRQ(ierr); 8622 PetscFunctionReturn(0); 8623 } 8624 if (!pointSF) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 8625 ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr); 8626 if (nroots < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 8627 ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 8628 ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 8629 8630 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 8631 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8632 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8633 for (l = 0; l < nleaves; ++l) { 8634 const PetscInt point = locals[l]; 8635 8636 if (point >= cStart && point < cEnd) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 8637 } 8638 8639 /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 8640 for (l = 0; l < nleaves; ++l) { 8641 const PetscInt point = locals[l]; 8642 const PetscInt *cone; 8643 PetscInt coneSize, c, idx; 8644 8645 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 8646 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 8647 for (c = 0; c < coneSize; ++c) { 8648 if (!rootdegree[cone[c]]) { 8649 ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr); 8650 if (idx < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 8651 } 8652 } 8653 } 8654 PetscFunctionReturn(0); 8655 } 8656 8657 PetscErrorCode DMPlexCheckAll_Internal(DM dm, PetscInt cellHeight) 8658 { 8659 PetscErrorCode ierr; 8660 8661 PetscFunctionBegin; 8662 ierr = DMPlexCheckSymmetry(dm);CHKERRQ(ierr); 8663 ierr = DMPlexCheckSkeleton(dm, cellHeight);CHKERRQ(ierr); 8664 ierr = DMPlexCheckFaces(dm, cellHeight);CHKERRQ(ierr); 8665 ierr = DMPlexCheckGeometry(dm);CHKERRQ(ierr); 8666 ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr); 8667 ierr = DMPlexCheckInterfaceCones(dm);CHKERRQ(ierr); 8668 PetscFunctionReturn(0); 8669 } 8670 8671 typedef struct cell_stats 8672 { 8673 PetscReal min, max, sum, squaresum; 8674 PetscInt count; 8675 } cell_stats_t; 8676 8677 static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8678 { 8679 PetscInt i, N = *len; 8680 8681 for (i = 0; i < N; i++) { 8682 cell_stats_t *A = (cell_stats_t *) a; 8683 cell_stats_t *B = (cell_stats_t *) b; 8684 8685 B->min = PetscMin(A->min,B->min); 8686 B->max = PetscMax(A->max,B->max); 8687 B->sum += A->sum; 8688 B->squaresum += A->squaresum; 8689 B->count += A->count; 8690 } 8691 } 8692 8693 /*@ 8694 DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8695 8696 Collective on dm 8697 8698 Input Parameters: 8699 + dm - The DMPlex object 8700 . output - If true, statistics will be displayed on stdout 8701 - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8702 8703 Notes: 8704 This is mainly intended for debugging/testing purposes. 8705 8706 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8707 8708 Level: developer 8709 8710 .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality() 8711 @*/ 8712 PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8713 { 8714 DM dmCoarse; 8715 cell_stats_t stats, globalStats; 8716 MPI_Comm comm = PetscObjectComm((PetscObject)dm); 8717 PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 8718 PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8719 PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 8720 PetscMPIInt rank,size; 8721 PetscErrorCode ierr; 8722 8723 PetscFunctionBegin; 8724 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8725 stats.min = PETSC_MAX_REAL; 8726 stats.max = PETSC_MIN_REAL; 8727 stats.sum = stats.squaresum = 0.; 8728 stats.count = 0; 8729 8730 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 8731 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8732 ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr); 8733 ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr); 8734 ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 8735 ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); 8736 for (c = cStart; c < cEnd; c++) { 8737 PetscInt i; 8738 PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8739 8740 ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 8741 if (detJ < 0.0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 8742 for (i = 0; i < PetscSqr(cdim); ++i) { 8743 frobJ += J[i] * J[i]; 8744 frobInvJ += invJ[i] * invJ[i]; 8745 } 8746 cond2 = frobJ * frobInvJ; 8747 cond = PetscSqrtReal(cond2); 8748 8749 stats.min = PetscMin(stats.min,cond); 8750 stats.max = PetscMax(stats.max,cond); 8751 stats.sum += cond; 8752 stats.squaresum += cond2; 8753 stats.count++; 8754 if (output && cond > limit) { 8755 PetscSection coordSection; 8756 Vec coordsLocal; 8757 PetscScalar *coords = NULL; 8758 PetscInt Nv, d, clSize, cl, *closure = NULL; 8759 8760 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8761 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8762 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8763 ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr); 8764 for (i = 0; i < Nv/cdim; ++i) { 8765 ierr = PetscSynchronizedPrintf(comm, " Vertex %D: (", i);CHKERRQ(ierr); 8766 for (d = 0; d < cdim; ++d) { 8767 if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);} 8768 ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr); 8769 } 8770 ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr); 8771 } 8772 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8773 for (cl = 0; cl < clSize*2; cl += 2) { 8774 const PetscInt edge = closure[cl]; 8775 8776 if ((edge >= eStart) && (edge < eEnd)) { 8777 PetscReal len; 8778 8779 ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr); 8780 ierr = PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr); 8781 } 8782 } 8783 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8784 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8785 } 8786 } 8787 if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 8788 8789 if (size > 1) { 8790 PetscMPIInt blockLengths[2] = {4,1}; 8791 MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8792 MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8793 MPI_Op statReduce; 8794 8795 ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRMPI(ierr); 8796 ierr = MPI_Type_commit(&statType);CHKERRMPI(ierr); 8797 ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRMPI(ierr); 8798 ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRMPI(ierr); 8799 ierr = MPI_Op_free(&statReduce);CHKERRMPI(ierr); 8800 ierr = MPI_Type_free(&statType);CHKERRMPI(ierr); 8801 } else { 8802 ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr); 8803 } 8804 if (rank == 0) { 8805 count = globalStats.count; 8806 min = globalStats.min; 8807 max = globalStats.max; 8808 mean = globalStats.sum / globalStats.count; 8809 stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8810 } 8811 8812 if (output) { 8813 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); 8814 } 8815 ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 8816 8817 ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 8818 if (dmCoarse) { 8819 PetscBool isplex; 8820 8821 ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 8822 if (isplex) { 8823 ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr); 8824 } 8825 } 8826 PetscFunctionReturn(0); 8827 } 8828 8829 /*@ 8830 DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8831 orthogonal quality below given tolerance. 8832 8833 Collective on dm 8834 8835 Input Parameters: 8836 + dm - The DMPlex object 8837 . fv - Optional PetscFV object for pre-computed cell/face centroid information 8838 - atol - [0, 1] Absolute tolerance for tagging cells. 8839 8840 Output Parameters: 8841 + OrthQual - Vec containing orthogonal quality per cell 8842 - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8843 8844 Options Database Keys: 8845 + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8846 supported. 8847 - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8848 8849 Notes: 8850 Orthogonal quality is given by the following formula: 8851 8852 \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8853 8854 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 8855 is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8856 current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8857 calculating the cosine of the angle between these vectors. 8858 8859 Orthogonal quality ranges from 1 (best) to 0 (worst). 8860 8861 This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8862 pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8863 8864 Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8865 8866 Level: intermediate 8867 8868 .seealso: DMPlexCheckCellShape(), DMCreateLabel() 8869 @*/ 8870 PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8871 { 8872 PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 8873 PetscInt *idx; 8874 PetscScalar *oqVals; 8875 const PetscScalar *cellGeomArr, *faceGeomArr; 8876 PetscReal *ci, *fi, *Ai; 8877 MPI_Comm comm; 8878 Vec cellgeom, facegeom; 8879 DM dmFace, dmCell; 8880 IS glob; 8881 ISLocalToGlobalMapping ltog; 8882 PetscViewer vwr; 8883 PetscErrorCode ierr; 8884 8885 PetscFunctionBegin; 8886 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8887 if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8888 PetscValidPointer(OrthQual, 4); 8889 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); 8890 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8891 ierr = DMGetDimension(dm, &nc);CHKERRQ(ierr); 8892 if (nc < 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc); 8893 { 8894 DMPlexInterpolatedFlag interpFlag; 8895 8896 ierr = DMPlexIsInterpolated(dm, &interpFlag);CHKERRQ(ierr); 8897 if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 8898 PetscMPIInt rank; 8899 8900 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8901 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 8902 } 8903 } 8904 if (OrthQualLabel) { 8905 PetscValidPointer(OrthQualLabel, 5); 8906 ierr = DMCreateLabel(dm, "Orthogonal_Quality");CHKERRQ(ierr); 8907 ierr = DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel);CHKERRQ(ierr); 8908 } else {*OrthQualLabel = NULL;} 8909 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8910 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8911 ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob);CHKERRQ(ierr); 8912 ierr = ISLocalToGlobalMappingCreateIS(glob, <og);CHKERRQ(ierr); 8913 ierr = ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 8914 ierr = VecCreate(comm, OrthQual);CHKERRQ(ierr); 8915 ierr = VecSetType(*OrthQual, VECSTANDARD);CHKERRQ(ierr); 8916 ierr = VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr); 8917 ierr = VecSetLocalToGlobalMapping(*OrthQual, ltog);CHKERRQ(ierr); 8918 ierr = VecSetUp(*OrthQual);CHKERRQ(ierr); 8919 ierr = ISDestroy(&glob);CHKERRQ(ierr); 8920 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 8921 ierr = DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL);CHKERRQ(ierr); 8922 ierr = VecGetArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8923 ierr = VecGetArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8924 ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr); 8925 ierr = VecGetDM(facegeom, &dmFace);CHKERRQ(ierr); 8926 ierr = PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai);CHKERRQ(ierr); 8927 for (cell = cStart; cell < cEnd; cellIter++,cell++) { 8928 PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 8929 PetscInt cellarr[2], *adj = NULL; 8930 PetscScalar *cArr, *fArr; 8931 PetscReal minvalc = 1.0, minvalf = 1.0; 8932 PetscFVCellGeom *cg; 8933 8934 idx[cellIter] = cell-cStart; 8935 cellarr[0] = cell; 8936 /* Make indexing into cellGeom easier */ 8937 ierr = DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg);CHKERRQ(ierr); 8938 ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj);CHKERRQ(ierr); 8939 /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 8940 ierr = PetscCalloc2(adjSize, &cArr, adjSize, &fArr);CHKERRQ(ierr); 8941 for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 8942 PetscInt i; 8943 const PetscInt neigh = adj[cellneigh]; 8944 PetscReal normci = 0, normfi = 0, normai = 0; 8945 PetscFVCellGeom *cgneigh; 8946 PetscFVFaceGeom *fg; 8947 8948 /* Don't count ourselves in the neighbor list */ 8949 if (neigh == cell) continue; 8950 ierr = DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh);CHKERRQ(ierr); 8951 cellarr[1] = neigh; 8952 { 8953 PetscInt numcovpts; 8954 const PetscInt *covpts; 8955 8956 ierr = DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 8957 ierr = DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg);CHKERRQ(ierr); 8958 ierr = DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 8959 } 8960 8961 /* Compute c_i, f_i and their norms */ 8962 for (i = 0; i < nc; i++) { 8963 ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 8964 fi[i] = fg->centroid[i] - cg->centroid[i]; 8965 Ai[i] = fg->normal[i]; 8966 normci += PetscPowReal(ci[i], 2); 8967 normfi += PetscPowReal(fi[i], 2); 8968 normai += PetscPowReal(Ai[i], 2); 8969 } 8970 normci = PetscSqrtReal(normci); 8971 normfi = PetscSqrtReal(normfi); 8972 normai = PetscSqrtReal(normai); 8973 8974 /* Normalize and compute for each face-cell-normal pair */ 8975 for (i = 0; i < nc; i++) { 8976 ci[i] = ci[i]/normci; 8977 fi[i] = fi[i]/normfi; 8978 Ai[i] = Ai[i]/normai; 8979 /* PetscAbs because I don't know if normals are guaranteed to point out */ 8980 cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 8981 fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 8982 } 8983 if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 8984 minvalc = PetscRealPart(cArr[cellneighiter]); 8985 } 8986 if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 8987 minvalf = PetscRealPart(fArr[cellneighiter]); 8988 } 8989 } 8990 ierr = PetscFree(adj);CHKERRQ(ierr); 8991 ierr = PetscFree2(cArr, fArr);CHKERRQ(ierr); 8992 /* Defer to cell if they're equal */ 8993 oqVals[cellIter] = PetscMin(minvalf, minvalc); 8994 if (OrthQualLabel) { 8995 if (PetscRealPart(oqVals[cellIter]) <= atol) {ierr = DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE);CHKERRQ(ierr);} 8996 } 8997 } 8998 ierr = VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES);CHKERRQ(ierr); 8999 ierr = VecAssemblyBegin(*OrthQual);CHKERRQ(ierr); 9000 ierr = VecAssemblyEnd(*OrthQual);CHKERRQ(ierr); 9001 ierr = VecRestoreArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 9002 ierr = VecRestoreArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 9003 ierr = PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL);CHKERRQ(ierr); 9004 if (OrthQualLabel) { 9005 if (vwr) {ierr = DMLabelView(*OrthQualLabel, vwr);CHKERRQ(ierr);} 9006 } 9007 ierr = PetscFree5(idx, oqVals, ci, fi, Ai);CHKERRQ(ierr); 9008 ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr); 9009 ierr = VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view");CHKERRQ(ierr); 9010 PetscFunctionReturn(0); 9011 } 9012 9013 /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 9014 * interpolator construction */ 9015 static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9016 { 9017 PetscSection section, newSection, gsection; 9018 PetscSF sf; 9019 PetscBool hasConstraints, ghasConstraints; 9020 PetscErrorCode ierr; 9021 9022 PetscFunctionBegin; 9023 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9024 PetscValidPointer(odm,2); 9025 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9026 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 9027 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 9028 if (!ghasConstraints) { 9029 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 9030 *odm = dm; 9031 PetscFunctionReturn(0); 9032 } 9033 ierr = DMClone(dm, odm);CHKERRQ(ierr); 9034 ierr = DMCopyFields(dm, *odm);CHKERRQ(ierr); 9035 ierr = DMGetLocalSection(*odm, &newSection);CHKERRQ(ierr); 9036 ierr = DMGetPointSF(*odm, &sf);CHKERRQ(ierr); 9037 ierr = PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 9038 ierr = DMSetGlobalSection(*odm, gsection);CHKERRQ(ierr); 9039 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 9040 PetscFunctionReturn(0); 9041 } 9042 9043 static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9044 { 9045 DM dmco, dmfo; 9046 Mat interpo; 9047 Vec rscale; 9048 Vec cglobalo, clocal; 9049 Vec fglobal, fglobalo, flocal; 9050 PetscBool regular; 9051 PetscErrorCode ierr; 9052 9053 PetscFunctionBegin; 9054 ierr = DMGetFullDM(dmc, &dmco);CHKERRQ(ierr); 9055 ierr = DMGetFullDM(dmf, &dmfo);CHKERRQ(ierr); 9056 ierr = DMSetCoarseDM(dmfo, dmco);CHKERRQ(ierr); 9057 ierr = DMPlexGetRegularRefinement(dmf, ®ular);CHKERRQ(ierr); 9058 ierr = DMPlexSetRegularRefinement(dmfo, regular);CHKERRQ(ierr); 9059 ierr = DMCreateInterpolation(dmco, dmfo, &interpo, &rscale);CHKERRQ(ierr); 9060 ierr = DMCreateGlobalVector(dmco, &cglobalo);CHKERRQ(ierr); 9061 ierr = DMCreateLocalVector(dmc, &clocal);CHKERRQ(ierr); 9062 ierr = VecSet(cglobalo, 0.);CHKERRQ(ierr); 9063 ierr = VecSet(clocal, 0.);CHKERRQ(ierr); 9064 ierr = DMCreateGlobalVector(dmf, &fglobal);CHKERRQ(ierr); 9065 ierr = DMCreateGlobalVector(dmfo, &fglobalo);CHKERRQ(ierr); 9066 ierr = DMCreateLocalVector(dmf, &flocal);CHKERRQ(ierr); 9067 ierr = VecSet(fglobal, 0.);CHKERRQ(ierr); 9068 ierr = VecSet(fglobalo, 0.);CHKERRQ(ierr); 9069 ierr = VecSet(flocal, 0.);CHKERRQ(ierr); 9070 ierr = DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL);CHKERRQ(ierr); 9071 ierr = DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9072 ierr = DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9073 ierr = MatMult(interpo, cglobalo, fglobalo);CHKERRQ(ierr); 9074 ierr = DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9075 ierr = DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9076 ierr = DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9077 ierr = DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9078 *shift = fglobal; 9079 ierr = VecDestroy(&flocal);CHKERRQ(ierr); 9080 ierr = VecDestroy(&fglobalo);CHKERRQ(ierr); 9081 ierr = VecDestroy(&clocal);CHKERRQ(ierr); 9082 ierr = VecDestroy(&cglobalo);CHKERRQ(ierr); 9083 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9084 ierr = MatDestroy(&interpo);CHKERRQ(ierr); 9085 ierr = DMDestroy(&dmfo);CHKERRQ(ierr); 9086 ierr = DMDestroy(&dmco);CHKERRQ(ierr); 9087 PetscFunctionReturn(0); 9088 } 9089 9090 PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9091 { 9092 PetscObject shifto; 9093 Vec shift; 9094 9095 PetscErrorCode ierr; 9096 9097 PetscFunctionBegin; 9098 if (!interp) { 9099 Vec rscale; 9100 9101 ierr = DMCreateInterpolation(coarse, fine, &interp, &rscale);CHKERRQ(ierr); 9102 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9103 } else { 9104 ierr = PetscObjectReference((PetscObject)interp);CHKERRQ(ierr); 9105 } 9106 ierr = PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto);CHKERRQ(ierr); 9107 if (!shifto) { 9108 ierr = DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift);CHKERRQ(ierr); 9109 ierr = PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift);CHKERRQ(ierr); 9110 shifto = (PetscObject) shift; 9111 ierr = VecDestroy(&shift);CHKERRQ(ierr); 9112 } 9113 shift = (Vec) shifto; 9114 ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr); 9115 ierr = VecAXPY(fineSol, 1.0, shift);CHKERRQ(ierr); 9116 ierr = MatDestroy(&interp);CHKERRQ(ierr); 9117 PetscFunctionReturn(0); 9118 } 9119 9120 /* Pointwise interpolation 9121 Just code FEM for now 9122 u^f = I u^c 9123 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 9124 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 9125 I_{ij} = psi^f_i phi^c_j 9126 */ 9127 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9128 { 9129 PetscSection gsc, gsf; 9130 PetscInt m, n; 9131 void *ctx; 9132 DM cdm; 9133 PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9134 PetscErrorCode ierr; 9135 9136 PetscFunctionBegin; 9137 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9138 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9139 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9140 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9141 9142 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 9143 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 9144 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9145 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 9146 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9147 9148 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9149 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9150 if (!isRefined || (regular && cdm == dmCoarse)) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx);CHKERRQ(ierr);} 9151 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 9152 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 9153 if (scaling) { 9154 /* Use naive scaling */ 9155 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 9156 } 9157 PetscFunctionReturn(0); 9158 } 9159 9160 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9161 { 9162 PetscErrorCode ierr; 9163 VecScatter ctx; 9164 9165 PetscFunctionBegin; 9166 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 9167 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 9168 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 9169 PetscFunctionReturn(0); 9170 } 9171 9172 static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9173 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9174 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9175 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 9176 { 9177 g0[0] = 1.0; 9178 } 9179 9180 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9181 { 9182 PetscSection gsc, gsf; 9183 PetscInt m, n; 9184 void *ctx; 9185 DM cdm; 9186 PetscBool regular; 9187 PetscErrorCode ierr; 9188 9189 PetscFunctionBegin; 9190 if (dmFine == dmCoarse) { 9191 DM dmc; 9192 PetscDS ds; 9193 Vec u; 9194 IS cellIS; 9195 PetscFormKey key; 9196 PetscInt depth; 9197 9198 ierr = DMClone(dmFine, &dmc);CHKERRQ(ierr); 9199 ierr = DMCopyDisc(dmFine, dmc);CHKERRQ(ierr); 9200 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9201 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9202 ierr = DMCreateMatrix(dmc, mass);CHKERRQ(ierr); 9203 ierr = DMGetGlobalVector(dmc, &u);CHKERRQ(ierr); 9204 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9205 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9206 ierr = MatZeroEntries(*mass);CHKERRQ(ierr); 9207 key.label = NULL; 9208 key.value = 0; 9209 key.field = 0; 9210 key.part = 0; 9211 ierr = DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL);CHKERRQ(ierr); 9212 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9213 ierr = DMRestoreGlobalVector(dmc, &u);CHKERRQ(ierr); 9214 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9215 } else { 9216 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9217 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9218 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9219 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9220 9221 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 9222 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9223 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 9224 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9225 9226 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9227 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9228 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9229 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9230 } 9231 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 9232 PetscFunctionReturn(0); 9233 } 9234 9235 /*@ 9236 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9237 9238 Input Parameter: 9239 . dm - The DMPlex object 9240 9241 Output Parameter: 9242 . regular - The flag 9243 9244 Level: intermediate 9245 9246 .seealso: DMPlexSetRegularRefinement() 9247 @*/ 9248 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 9249 { 9250 PetscFunctionBegin; 9251 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9252 PetscValidPointer(regular, 2); 9253 *regular = ((DM_Plex *) dm->data)->regularRefinement; 9254 PetscFunctionReturn(0); 9255 } 9256 9257 /*@ 9258 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9259 9260 Input Parameters: 9261 + dm - The DMPlex object 9262 - regular - The flag 9263 9264 Level: intermediate 9265 9266 .seealso: DMPlexGetRegularRefinement() 9267 @*/ 9268 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 9269 { 9270 PetscFunctionBegin; 9271 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9272 ((DM_Plex *) dm->data)->regularRefinement = regular; 9273 PetscFunctionReturn(0); 9274 } 9275 9276 /* anchors */ 9277 /*@ 9278 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9279 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 9280 9281 not collective 9282 9283 Input Parameter: 9284 . dm - The DMPlex object 9285 9286 Output Parameters: 9287 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9288 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9289 9290 Level: intermediate 9291 9292 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 9293 @*/ 9294 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9295 { 9296 DM_Plex *plex = (DM_Plex *)dm->data; 9297 PetscErrorCode ierr; 9298 9299 PetscFunctionBegin; 9300 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9301 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 9302 if (anchorSection) *anchorSection = plex->anchorSection; 9303 if (anchorIS) *anchorIS = plex->anchorIS; 9304 PetscFunctionReturn(0); 9305 } 9306 9307 /*@ 9308 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9309 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9310 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9311 9312 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9313 DMGetConstraints() and filling in the entries in the constraint matrix. 9314 9315 collective on dm 9316 9317 Input Parameters: 9318 + dm - The DMPlex object 9319 . 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). 9320 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9321 9322 The reference counts of anchorSection and anchorIS are incremented. 9323 9324 Level: intermediate 9325 9326 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 9327 @*/ 9328 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9329 { 9330 DM_Plex *plex = (DM_Plex *)dm->data; 9331 PetscMPIInt result; 9332 PetscErrorCode ierr; 9333 9334 PetscFunctionBegin; 9335 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9336 if (anchorSection) { 9337 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 9338 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRMPI(ierr); 9339 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9340 } 9341 if (anchorIS) { 9342 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 9343 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRMPI(ierr); 9344 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9345 } 9346 9347 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 9348 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 9349 plex->anchorSection = anchorSection; 9350 9351 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 9352 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 9353 plex->anchorIS = anchorIS; 9354 9355 if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9356 PetscInt size, a, pStart, pEnd; 9357 const PetscInt *anchors; 9358 9359 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9360 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 9361 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 9362 for (a = 0; a < size; a++) { 9363 PetscInt p; 9364 9365 p = anchors[a]; 9366 if (p >= pStart && p < pEnd) { 9367 PetscInt dof; 9368 9369 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9370 if (dof) { 9371 PetscErrorCode ierr2; 9372 9373 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 9374 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 9375 } 9376 } 9377 } 9378 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 9379 } 9380 /* reset the generic constraints */ 9381 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 9382 PetscFunctionReturn(0); 9383 } 9384 9385 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9386 { 9387 PetscSection anchorSection; 9388 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9389 PetscErrorCode ierr; 9390 9391 PetscFunctionBegin; 9392 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9393 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9394 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 9395 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9396 if (numFields) { 9397 PetscInt f; 9398 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 9399 9400 for (f = 0; f < numFields; f++) { 9401 PetscInt numComp; 9402 9403 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 9404 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 9405 } 9406 } 9407 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9408 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9409 pStart = PetscMax(pStart,sStart); 9410 pEnd = PetscMin(pEnd,sEnd); 9411 pEnd = PetscMax(pStart,pEnd); 9412 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 9413 for (p = pStart; p < pEnd; p++) { 9414 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9415 if (dof) { 9416 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 9417 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 9418 for (f = 0; f < numFields; f++) { 9419 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 9420 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 9421 } 9422 } 9423 } 9424 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 9425 ierr = PetscObjectSetName((PetscObject) *cSec, "Constraint Section");CHKERRQ(ierr); 9426 PetscFunctionReturn(0); 9427 } 9428 9429 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9430 { 9431 PetscSection aSec; 9432 PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 9433 const PetscInt *anchors; 9434 PetscInt numFields, f; 9435 IS aIS; 9436 PetscErrorCode ierr; 9437 MatType mtype; 9438 PetscBool iscuda,iskokkos; 9439 9440 PetscFunctionBegin; 9441 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9442 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 9443 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 9444 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 9445 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 9446 ierr = PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr); 9447 if (!iscuda) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr); } 9448 ierr = PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos);CHKERRQ(ierr); 9449 if (!iskokkos) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos);CHKERRQ(ierr); } 9450 if (iscuda) mtype = MATSEQAIJCUSPARSE; 9451 else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9452 else mtype = MATSEQAIJ; 9453 ierr = MatSetType(*cMat,mtype);CHKERRQ(ierr); 9454 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 9455 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 9456 /* cSec will be a subset of aSec and section */ 9457 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 9458 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9459 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 9460 i[0] = 0; 9461 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9462 for (p = pStart; p < pEnd; p++) { 9463 PetscInt rDof, rOff, r; 9464 9465 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9466 if (!rDof) continue; 9467 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9468 if (numFields) { 9469 for (f = 0; f < numFields; f++) { 9470 annz = 0; 9471 for (r = 0; r < rDof; r++) { 9472 a = anchors[rOff + r]; 9473 if (a < sStart || a >= sEnd) continue; 9474 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9475 annz += aDof; 9476 } 9477 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9478 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 9479 for (q = 0; q < dof; q++) { 9480 i[off + q + 1] = i[off + q] + annz; 9481 } 9482 } 9483 } else { 9484 annz = 0; 9485 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9486 for (q = 0; q < dof; q++) { 9487 a = anchors[rOff + q]; 9488 if (a < sStart || a >= sEnd) continue; 9489 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9490 annz += aDof; 9491 } 9492 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9493 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 9494 for (q = 0; q < dof; q++) { 9495 i[off + q + 1] = i[off + q] + annz; 9496 } 9497 } 9498 } 9499 nnz = i[m]; 9500 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 9501 offset = 0; 9502 for (p = pStart; p < pEnd; p++) { 9503 if (numFields) { 9504 for (f = 0; f < numFields; f++) { 9505 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9506 for (q = 0; q < dof; q++) { 9507 PetscInt rDof, rOff, r; 9508 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9509 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9510 for (r = 0; r < rDof; r++) { 9511 PetscInt s; 9512 9513 a = anchors[rOff + r]; 9514 if (a < sStart || a >= sEnd) continue; 9515 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9516 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 9517 for (s = 0; s < aDof; s++) { 9518 j[offset++] = aOff + s; 9519 } 9520 } 9521 } 9522 } 9523 } else { 9524 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9525 for (q = 0; q < dof; q++) { 9526 PetscInt rDof, rOff, r; 9527 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9528 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9529 for (r = 0; r < rDof; r++) { 9530 PetscInt s; 9531 9532 a = anchors[rOff + r]; 9533 if (a < sStart || a >= sEnd) continue; 9534 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9535 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 9536 for (s = 0; s < aDof; s++) { 9537 j[offset++] = aOff + s; 9538 } 9539 } 9540 } 9541 } 9542 } 9543 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 9544 ierr = PetscFree(i);CHKERRQ(ierr); 9545 ierr = PetscFree(j);CHKERRQ(ierr); 9546 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 9547 PetscFunctionReturn(0); 9548 } 9549 9550 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 9551 { 9552 DM_Plex *plex = (DM_Plex *)dm->data; 9553 PetscSection anchorSection, section, cSec; 9554 Mat cMat; 9555 PetscErrorCode ierr; 9556 9557 PetscFunctionBegin; 9558 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9559 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9560 if (anchorSection) { 9561 PetscInt Nf; 9562 9563 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 9564 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 9565 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 9566 ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 9567 if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 9568 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 9569 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 9570 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 9571 } 9572 PetscFunctionReturn(0); 9573 } 9574 9575 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9576 { 9577 IS subis; 9578 PetscSection section, subsection; 9579 PetscErrorCode ierr; 9580 9581 PetscFunctionBegin; 9582 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9583 if (!section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 9584 if (!subdm) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9585 /* Create subdomain */ 9586 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 9587 /* Create submodel */ 9588 ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr); 9589 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 9590 ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr); 9591 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 9592 ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 9593 /* Create map from submodel to global model */ 9594 if (is) { 9595 PetscSection sectionGlobal, subsectionGlobal; 9596 IS spIS; 9597 const PetscInt *spmap; 9598 PetscInt *subIndices; 9599 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9600 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9601 9602 ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 9603 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 9604 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 9605 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 9606 ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 9607 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 9608 for (p = pStart; p < pEnd; ++p) { 9609 PetscInt gdof, pSubSize = 0; 9610 9611 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 9612 if (gdof > 0) { 9613 for (f = 0; f < Nf; ++f) { 9614 PetscInt fdof, fcdof; 9615 9616 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 9617 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 9618 pSubSize += fdof-fcdof; 9619 } 9620 subSize += pSubSize; 9621 if (pSubSize) { 9622 if (bs < 0) { 9623 bs = pSubSize; 9624 } else if (bs != pSubSize) { 9625 /* Layout does not admit a pointwise block size */ 9626 bs = 1; 9627 } 9628 } 9629 } 9630 } 9631 /* Must have same blocksize on all procs (some might have no points) */ 9632 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 9633 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 9634 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9635 else {bs = bsMinMax[0];} 9636 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 9637 for (p = pStart; p < pEnd; ++p) { 9638 PetscInt gdof, goff; 9639 9640 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 9641 if (gdof > 0) { 9642 const PetscInt point = spmap[p]; 9643 9644 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 9645 for (f = 0; f < Nf; ++f) { 9646 PetscInt fdof, fcdof, fc, f2, poff = 0; 9647 9648 /* Can get rid of this loop by storing field information in the global section */ 9649 for (f2 = 0; f2 < f; ++f2) { 9650 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 9651 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 9652 poff += fdof-fcdof; 9653 } 9654 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 9655 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 9656 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9657 subIndices[subOff] = goff+poff+fc; 9658 } 9659 } 9660 } 9661 } 9662 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 9663 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 9664 if (bs > 1) { 9665 /* We need to check that the block size does not come from non-contiguous fields */ 9666 PetscInt i, j, set = 1; 9667 for (i = 0; i < subSize; i += bs) { 9668 for (j = 0; j < bs; ++j) { 9669 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9670 } 9671 } 9672 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 9673 } 9674 /* Attach nullspace */ 9675 for (f = 0; f < Nf; ++f) { 9676 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9677 if ((*subdm)->nullspaceConstructors[f]) break; 9678 } 9679 if (f < Nf) { 9680 MatNullSpace nullSpace; 9681 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace);CHKERRQ(ierr); 9682 9683 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 9684 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 9685 } 9686 } 9687 PetscFunctionReturn(0); 9688 } 9689 9690 /*@ 9691 DMPlexMonitorThroughput - Report the cell throughput of FE integration 9692 9693 Input Parameter: 9694 - dm - The DM 9695 9696 Level: developer 9697 9698 Options Database Keys: 9699 . -dm_plex_monitor_throughput - Activate the monitor 9700 9701 .seealso: DMSetFromOptions(), DMPlexCreate() 9702 @*/ 9703 PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9704 { 9705 #if defined(PETSC_USE_LOG) 9706 PetscStageLog stageLog; 9707 PetscLogEvent event; 9708 PetscLogStage stage; 9709 PetscEventPerfInfo eventInfo; 9710 PetscReal cellRate, flopRate; 9711 PetscInt cStart, cEnd, Nf, N; 9712 const char *name; 9713 PetscErrorCode ierr; 9714 #endif 9715 9716 PetscFunctionBegin; 9717 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9718 #if defined(PETSC_USE_LOG) 9719 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 9720 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9721 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9722 ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 9723 ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr); 9724 ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr); 9725 ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr); 9726 N = (cEnd - cStart)*Nf*eventInfo.count; 9727 flopRate = eventInfo.flops/eventInfo.time; 9728 cellRate = N/eventInfo.time; 9729 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); 9730 #else 9731 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9732 #endif 9733 PetscFunctionReturn(0); 9734 } 9735