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