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