1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petsc/private/isimpl.h> 3 #include <petsc/private/vecimpl.h> 4 #include <petsc/private/glvisvecimpl.h> 5 #include <petscsf.h> 6 #include <petscds.h> 7 #include <petscdraw.h> 8 #include <petscdmfield.h> 9 #include <petscdmplextransform.h> 10 11 /* Logging support */ 12 PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF,DMPLEX_LocatePoints; 13 14 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 15 16 /*@ 17 DMPlexIsSimplex - Is the first cell in this mesh a simplex? 18 19 Input Parameter: 20 . dm - The DMPlex object 21 22 Output Parameter: 23 . simplex - Flag checking for a simplex 24 25 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 26 If the mesh has no cells, this returns PETSC_FALSE. 27 28 Level: intermediate 29 30 .seealso DMPlexGetSimplexOrBoxCells(), DMPlexGetCellType(), DMPlexGetHeightStratum(), DMPolytopeTypeGetNumVertices() 31 @*/ 32 PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 33 { 34 DMPolytopeType ct; 35 PetscInt cStart, cEnd; 36 PetscErrorCode ierr; 37 38 PetscFunctionBegin; 39 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 40 if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);} 41 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 42 *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 43 PetscFunctionReturn(0); 44 } 45 46 /*@ 47 DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 48 49 Input Parameters: 50 + dm - The DMPlex object 51 - height - The cell height in the Plex, 0 is the default 52 53 Output Parameters: 54 + cStart - The first "normal" cell 55 - cEnd - The upper bound on "normal"" cells 56 57 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 58 59 Level: developer 60 61 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 62 @*/ 63 PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 64 { 65 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 66 PetscInt cS, cE, c; 67 PetscErrorCode ierr; 68 69 PetscFunctionBegin; 70 ierr = DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE);CHKERRQ(ierr); 71 for (c = cS; c < cE; ++c) { 72 DMPolytopeType cct; 73 74 ierr = DMPlexGetCellType(dm, c, &cct);CHKERRQ(ierr); 75 if ((PetscInt) cct < 0) break; 76 switch (cct) { 77 case DM_POLYTOPE_POINT: 78 case DM_POLYTOPE_SEGMENT: 79 case DM_POLYTOPE_TRIANGLE: 80 case DM_POLYTOPE_QUADRILATERAL: 81 case DM_POLYTOPE_TETRAHEDRON: 82 case DM_POLYTOPE_HEXAHEDRON: 83 ct = cct; 84 break; 85 default: break; 86 } 87 if (ct != DM_POLYTOPE_UNKNOWN) break; 88 } 89 if (ct != DM_POLYTOPE_UNKNOWN) { 90 DMLabel ctLabel; 91 92 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 93 ierr = DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE);CHKERRQ(ierr); 94 } 95 if (cStart) *cStart = cS; 96 if (cEnd) *cEnd = cE; 97 PetscFunctionReturn(0); 98 } 99 100 PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 101 { 102 PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 103 PetscInt vcdof[2] = {0,0}, globalvcdof[2]; 104 PetscErrorCode ierr; 105 106 PetscFunctionBegin; 107 *ft = PETSC_VTK_INVALID; 108 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 109 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 110 ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 111 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 112 if (field >= 0) { 113 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]);CHKERRQ(ierr);} 114 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]);CHKERRQ(ierr);} 115 } else { 116 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vcdof[0]);CHKERRQ(ierr);} 117 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &vcdof[1]);CHKERRQ(ierr);} 118 } 119 ierr = MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 120 if (globalvcdof[0]) { 121 *sStart = vStart; 122 *sEnd = vEnd; 123 if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 124 else *ft = PETSC_VTK_POINT_FIELD; 125 } else if (globalvcdof[1]) { 126 *sStart = cStart; 127 *sEnd = cEnd; 128 if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 129 else *ft = PETSC_VTK_CELL_FIELD; 130 } else { 131 if (field >= 0) { 132 const char *fieldname; 133 134 ierr = PetscSectionGetFieldName(section, field, &fieldname);CHKERRQ(ierr); 135 ierr = PetscInfo2((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname);CHKERRQ(ierr); 136 } else { 137 ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\"%s\"\n");CHKERRQ(ierr); 138 } 139 } 140 PetscFunctionReturn(0); 141 } 142 143 static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 144 { 145 DM dm; 146 PetscSection s; 147 PetscDraw draw, popup; 148 DM cdm; 149 PetscSection coordSection; 150 Vec coordinates; 151 const PetscScalar *coords, *array; 152 PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 153 PetscReal vbound[2], time; 154 PetscBool isnull, flg; 155 PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 156 const char *name; 157 char title[PETSC_MAX_PATH_LEN]; 158 PetscErrorCode ierr; 159 160 PetscFunctionBegin; 161 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 162 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 163 if (isnull) PetscFunctionReturn(0); 164 165 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 166 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 167 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D. Use PETSCVIEWERGLVIS", dim); 168 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 169 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 170 ierr = DMGetCoarsenLevel(dm, &level);CHKERRQ(ierr); 171 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 172 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 173 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 174 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 175 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 176 177 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 178 ierr = DMGetOutputSequenceNumber(dm, &step, &time);CHKERRQ(ierr); 179 180 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 181 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 182 for (c = 0; c < N; c += dim) { 183 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 184 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 185 } 186 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 187 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 188 189 /* Could implement something like DMDASelectFields() */ 190 for (f = 0; f < Nf; ++f) { 191 DM fdm = dm; 192 Vec fv = v; 193 IS fis; 194 char prefix[PETSC_MAX_PATH_LEN]; 195 const char *fname; 196 197 ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr); 198 ierr = PetscSectionGetFieldName(s, f, &fname);CHKERRQ(ierr); 199 200 if (v->hdr.prefix) {ierr = PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix));CHKERRQ(ierr);} 201 else {prefix[0] = '\0';} 202 if (Nf > 1) { 203 ierr = DMCreateSubDM(dm, 1, &f, &fis, &fdm);CHKERRQ(ierr); 204 ierr = VecGetSubVector(v, fis, &fv);CHKERRQ(ierr); 205 ierr = PetscStrlcat(prefix, fname,sizeof(prefix));CHKERRQ(ierr); 206 ierr = PetscStrlcat(prefix, "_",sizeof(prefix));CHKERRQ(ierr); 207 } 208 for (comp = 0; comp < Nc; ++comp, ++w) { 209 PetscInt nmax = 2; 210 211 ierr = PetscViewerDrawGetDraw(viewer, w, &draw);CHKERRQ(ierr); 212 if (Nc > 1) {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time);CHKERRQ(ierr);} 213 else {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time);CHKERRQ(ierr);} 214 ierr = PetscDrawSetTitle(draw, title);CHKERRQ(ierr); 215 216 /* TODO Get max and min only for this component */ 217 ierr = PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg);CHKERRQ(ierr); 218 if (!flg) { 219 ierr = VecMin(fv, NULL, &vbound[0]);CHKERRQ(ierr); 220 ierr = VecMax(fv, NULL, &vbound[1]);CHKERRQ(ierr); 221 if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 222 } 223 ierr = PetscDrawGetPopup(draw, &popup);CHKERRQ(ierr); 224 ierr = PetscDrawScalePopup(popup, vbound[0], vbound[1]);CHKERRQ(ierr); 225 ierr = PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]);CHKERRQ(ierr); 226 227 ierr = VecGetArrayRead(fv, &array);CHKERRQ(ierr); 228 for (c = cStart; c < cEnd; ++c) { 229 PetscScalar *coords = NULL, *a = NULL; 230 PetscInt numCoords, color[4] = {-1,-1,-1,-1}; 231 232 ierr = DMPlexPointLocalRead(fdm, c, array, &a);CHKERRQ(ierr); 233 if (a) { 234 color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 235 color[1] = color[2] = color[3] = color[0]; 236 } else { 237 PetscScalar *vals = NULL; 238 PetscInt numVals, va; 239 240 ierr = DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 241 if (numVals % Nc) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %D does not divide the number of values in the closure %D", Nc, numVals); 242 switch (numVals/Nc) { 243 case 3: /* P1 Triangle */ 244 case 4: /* P1 Quadrangle */ 245 for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]); 246 break; 247 case 6: /* P2 Triangle */ 248 case 8: /* P2 Quadrangle */ 249 for (va = 0; va < numVals/(Nc*2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp + numVals/(Nc*2)]), vbound[0], vbound[1]); 250 break; 251 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc); 252 } 253 ierr = DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 254 } 255 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 256 switch (numCoords) { 257 case 6: 258 case 12: /* Localized triangle */ 259 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 260 break; 261 case 8: 262 case 16: /* Localized quadrilateral */ 263 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 264 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0]);CHKERRQ(ierr); 265 break; 266 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords); 267 } 268 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 269 } 270 ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr); 271 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 272 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 273 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 274 } 275 if (Nf > 1) { 276 ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr); 277 ierr = ISDestroy(&fis);CHKERRQ(ierr); 278 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 279 } 280 } 281 PetscFunctionReturn(0); 282 } 283 284 static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 285 { 286 DM dm; 287 Vec locv; 288 const char *name; 289 PetscSection section; 290 PetscInt pStart, pEnd; 291 PetscInt numFields; 292 PetscViewerVTKFieldType ft; 293 PetscErrorCode ierr; 294 295 PetscFunctionBegin; 296 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 297 ierr = DMCreateLocalVector(dm, &locv);CHKERRQ(ierr); /* VTK viewer requires exclusive ownership of the vector */ 298 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 299 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 300 ierr = VecCopy(v, locv);CHKERRQ(ierr); 301 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 302 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 303 if (!numFields) { 304 ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 305 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 306 } else { 307 PetscInt f; 308 309 for (f = 0; f < numFields; f++) { 310 ierr = DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft);CHKERRQ(ierr); 311 if (ft == PETSC_VTK_INVALID) continue; 312 ierr = PetscObjectReference((PetscObject)locv);CHKERRQ(ierr); 313 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 314 } 315 ierr = VecDestroy(&locv);CHKERRQ(ierr); 316 } 317 PetscFunctionReturn(0); 318 } 319 320 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 321 { 322 DM dm; 323 PetscBool isvtk, ishdf5, isdraw, isglvis; 324 PetscErrorCode ierr; 325 326 PetscFunctionBegin; 327 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 328 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 329 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 330 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 331 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 332 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 333 if (isvtk || ishdf5 || isdraw || isglvis) { 334 PetscInt i,numFields; 335 PetscObject fe; 336 PetscBool fem = PETSC_FALSE; 337 Vec locv = v; 338 const char *name; 339 PetscInt step; 340 PetscReal time; 341 342 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 343 for (i=0; i<numFields; i++) { 344 ierr = DMGetField(dm, i, NULL, &fe);CHKERRQ(ierr); 345 if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; } 346 } 347 if (fem) { 348 PetscObject isZero; 349 350 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 351 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 352 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 353 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 354 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 355 ierr = VecCopy(v, locv);CHKERRQ(ierr); 356 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 357 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr); 358 } 359 if (isvtk) { 360 ierr = VecView_Plex_Local_VTK(locv, viewer);CHKERRQ(ierr); 361 } else if (ishdf5) { 362 #if defined(PETSC_HAVE_HDF5) 363 ierr = VecView_Plex_Local_HDF5_Internal(locv, viewer);CHKERRQ(ierr); 364 #else 365 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 366 #endif 367 } else if (isdraw) { 368 ierr = VecView_Plex_Local_Draw(locv, viewer);CHKERRQ(ierr); 369 } else if (isglvis) { 370 ierr = DMGetOutputSequenceNumber(dm, &step, NULL);CHKERRQ(ierr); 371 ierr = PetscViewerGLVisSetSnapId(viewer, step);CHKERRQ(ierr); 372 ierr = VecView_GLVis(locv, viewer);CHKERRQ(ierr); 373 } 374 if (fem) { 375 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 376 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 377 } 378 } else { 379 PetscBool isseq; 380 381 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 382 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 383 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 384 } 385 PetscFunctionReturn(0); 386 } 387 388 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 389 { 390 DM dm; 391 PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii; 392 PetscErrorCode ierr; 393 394 PetscFunctionBegin; 395 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 396 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 397 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 398 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 399 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 400 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 401 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 402 if (isvtk || isdraw || isglvis) { 403 Vec locv; 404 PetscObject isZero; 405 const char *name; 406 407 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 408 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 409 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 410 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 411 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 412 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 413 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 414 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 415 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 416 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 417 } else if (ishdf5) { 418 #if defined(PETSC_HAVE_HDF5) 419 ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 420 #else 421 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 422 #endif 423 } else if (isexodusii) { 424 #if defined(PETSC_HAVE_EXODUSII) 425 ierr = VecView_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 426 #else 427 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 428 #endif 429 } else { 430 PetscBool isseq; 431 432 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 433 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 434 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 435 } 436 PetscFunctionReturn(0); 437 } 438 439 PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 440 { 441 DM dm; 442 MPI_Comm comm; 443 PetscViewerFormat format; 444 Vec v; 445 PetscBool isvtk, ishdf5; 446 PetscErrorCode ierr; 447 448 PetscFunctionBegin; 449 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 450 ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 451 if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 452 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 453 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 454 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 455 if (format == PETSC_VIEWER_NATIVE) { 456 /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 457 /* this need a better fix */ 458 if (dm->useNatural) { 459 if (dm->sfNatural) { 460 const char *vecname; 461 PetscInt n, nroots; 462 463 ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr); 464 ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 465 if (n == nroots) { 466 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 467 ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 468 ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 469 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 470 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 471 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 472 } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 473 } else v = originalv; 474 } else v = originalv; 475 476 if (ishdf5) { 477 #if defined(PETSC_HAVE_HDF5) 478 ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 479 #else 480 SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 481 #endif 482 } else if (isvtk) { 483 SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 484 } else { 485 PetscBool isseq; 486 487 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 488 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 489 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 490 } 491 if (v != originalv) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 492 PetscFunctionReturn(0); 493 } 494 495 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 496 { 497 DM dm; 498 PetscBool ishdf5; 499 PetscErrorCode ierr; 500 501 PetscFunctionBegin; 502 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 503 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 504 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 505 if (ishdf5) { 506 DM dmBC; 507 Vec gv; 508 const char *name; 509 510 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 511 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 512 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 513 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 514 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 515 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 516 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 517 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 518 } else { 519 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 520 } 521 PetscFunctionReturn(0); 522 } 523 524 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 525 { 526 DM dm; 527 PetscBool ishdf5,isexodusii; 528 PetscErrorCode ierr; 529 530 PetscFunctionBegin; 531 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 532 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 533 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 534 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 535 if (ishdf5) { 536 #if defined(PETSC_HAVE_HDF5) 537 ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 538 #else 539 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 540 #endif 541 } else if (isexodusii) { 542 #if defined(PETSC_HAVE_EXODUSII) 543 ierr = VecLoad_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 544 #else 545 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 546 #endif 547 } else { 548 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 549 } 550 PetscFunctionReturn(0); 551 } 552 553 PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 554 { 555 DM dm; 556 PetscViewerFormat format; 557 PetscBool ishdf5; 558 PetscErrorCode ierr; 559 560 PetscFunctionBegin; 561 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 562 if (!dm) SETERRQ(PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 563 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 564 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 565 if (format == PETSC_VIEWER_NATIVE) { 566 if (dm->useNatural) { 567 if (dm->sfNatural) { 568 if (ishdf5) { 569 #if defined(PETSC_HAVE_HDF5) 570 Vec v; 571 const char *vecname; 572 573 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 574 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 575 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 576 ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 577 ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 578 ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 579 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 580 #else 581 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 582 #endif 583 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 584 } 585 } else { 586 ierr = VecLoad_Default(originalv, viewer);CHKERRQ(ierr); 587 } 588 } 589 PetscFunctionReturn(0); 590 } 591 592 PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 593 { 594 PetscSection coordSection; 595 Vec coordinates; 596 DMLabel depthLabel, celltypeLabel; 597 const char *name[4]; 598 const PetscScalar *a; 599 PetscInt dim, pStart, pEnd, cStart, cEnd, c; 600 PetscErrorCode ierr; 601 602 PetscFunctionBegin; 603 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 604 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 605 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 606 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 607 ierr = DMPlexGetCellTypeLabel(dm, &celltypeLabel);CHKERRQ(ierr); 608 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 609 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 610 ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 611 name[0] = "vertex"; 612 name[1] = "edge"; 613 name[dim-1] = "face"; 614 name[dim] = "cell"; 615 for (c = cStart; c < cEnd; ++c) { 616 PetscInt *closure = NULL; 617 PetscInt closureSize, cl, ct; 618 619 ierr = DMLabelGetValue(celltypeLabel, c, &ct);CHKERRQ(ierr); 620 ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]);CHKERRQ(ierr); 621 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 622 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 623 for (cl = 0; cl < closureSize*2; cl += 2) { 624 PetscInt point = closure[cl], depth, dof, off, d, p; 625 626 if ((point < pStart) || (point >= pEnd)) continue; 627 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 628 if (!dof) continue; 629 ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 630 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 631 ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr); 632 for (p = 0; p < dof/dim; ++p) { 633 ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 634 for (d = 0; d < dim; ++d) { 635 if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 636 ierr = PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 637 } 638 ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 639 } 640 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 641 } 642 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 643 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 644 } 645 ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 646 PetscFunctionReturn(0); 647 } 648 649 typedef enum {CS_CARTESIAN, CS_POLAR, CS_CYLINDRICAL, CS_SPHERICAL} CoordSystem; 650 const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 651 652 static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 653 { 654 PetscInt i; 655 PetscErrorCode ierr; 656 657 PetscFunctionBegin; 658 if (dim > 3) { 659 for (i = 0; i < dim; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) PetscRealPart(x[i]));CHKERRQ(ierr);} 660 } else { 661 PetscReal coords[3], trcoords[3]; 662 663 for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 664 switch (cs) { 665 case CS_CARTESIAN: for (i = 0; i < dim; ++i) trcoords[i] = coords[i];break; 666 case CS_POLAR: 667 if (dim != 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %D", dim); 668 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 669 trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 670 break; 671 case CS_CYLINDRICAL: 672 if (dim != 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %D", dim); 673 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 674 trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 675 trcoords[2] = coords[2]; 676 break; 677 case CS_SPHERICAL: 678 if (dim != 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %D", dim); 679 trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 680 trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 681 trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 682 break; 683 } 684 for (i = 0; i < dim; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) trcoords[i]);CHKERRQ(ierr);} 685 } 686 PetscFunctionReturn(0); 687 } 688 689 static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 690 { 691 DM_Plex *mesh = (DM_Plex*) dm->data; 692 DM cdm; 693 PetscSection coordSection; 694 Vec coordinates; 695 PetscViewerFormat format; 696 PetscErrorCode ierr; 697 698 PetscFunctionBegin; 699 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 700 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 701 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 702 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 703 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 704 const char *name; 705 PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 706 PetscInt pStart, pEnd, p, numLabels, l; 707 PetscMPIInt rank, size; 708 709 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 710 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 711 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 712 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 713 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 714 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 715 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 716 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 717 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 718 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 719 ierr = PetscViewerASCIIPrintf(viewer, "Supports:\n", name);CHKERRQ(ierr); 720 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 721 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize);CHKERRQ(ierr); 722 for (p = pStart; p < pEnd; ++p) { 723 PetscInt dof, off, s; 724 725 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 726 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 727 for (s = off; s < off+dof; ++s) { 728 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 729 } 730 } 731 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 732 ierr = PetscViewerASCIIPrintf(viewer, "Cones:\n", name);CHKERRQ(ierr); 733 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize);CHKERRQ(ierr); 734 for (p = pStart; p < pEnd; ++p) { 735 PetscInt dof, off, c; 736 737 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 738 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 739 for (c = off; c < off+dof; ++c) { 740 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 741 } 742 } 743 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 744 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 745 if (coordSection && coordinates) { 746 CoordSystem cs = CS_CARTESIAN; 747 const PetscScalar *array; 748 PetscInt Nf, Nc, pStart, pEnd, p; 749 PetscMPIInt rank; 750 const char *name; 751 752 ierr = PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL);CHKERRQ(ierr); 753 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRMPI(ierr); 754 ierr = PetscSectionGetNumFields(coordSection, &Nf);CHKERRQ(ierr); 755 if (Nf != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %D", Nf); 756 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 757 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 758 ierr = PetscObjectGetName((PetscObject) coordinates, &name);CHKERRQ(ierr); 759 ierr = PetscViewerASCIIPrintf(viewer, "%s with %D fields\n", name, Nf);CHKERRQ(ierr); 760 ierr = PetscViewerASCIIPrintf(viewer, " field 0 with %D components\n", Nc);CHKERRQ(ierr); 761 if (cs != CS_CARTESIAN) {ierr = PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs]);CHKERRQ(ierr);} 762 763 ierr = VecGetArrayRead(coordinates, &array);CHKERRQ(ierr); 764 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 765 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank);CHKERRQ(ierr); 766 for (p = pStart; p < pEnd; ++p) { 767 PetscInt dof, off; 768 769 ierr = PetscSectionGetDof(coordSection, p, &dof);CHKERRQ(ierr); 770 ierr = PetscSectionGetOffset(coordSection, p, &off);CHKERRQ(ierr); 771 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " (%4D) dim %2D offset %3D", p, dof, off);CHKERRQ(ierr); 772 ierr = DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]);CHKERRQ(ierr); 773 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\n");CHKERRQ(ierr); 774 } 775 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 776 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 777 ierr = VecRestoreArrayRead(coordinates, &array);CHKERRQ(ierr); 778 } 779 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 780 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 781 for (l = 0; l < numLabels; ++l) { 782 DMLabel label; 783 PetscBool isdepth; 784 const char *name; 785 786 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 787 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 788 if (isdepth) continue; 789 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 790 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 791 } 792 if (size > 1) { 793 PetscSF sf; 794 795 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 796 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 797 } 798 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 799 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 800 const char *name, *color; 801 const char *defcolors[3] = {"gray", "orange", "green"}; 802 const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 803 char lname[PETSC_MAX_PATH_LEN]; 804 PetscReal scale = 2.0; 805 PetscReal tikzscale = 1.0; 806 PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 807 double tcoords[3]; 808 PetscScalar *coords; 809 PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 810 PetscMPIInt rank, size; 811 char **names, **colors, **lcolors; 812 PetscBool flg, lflg; 813 PetscBT wp = NULL; 814 PetscInt pEnd, pStart; 815 816 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 817 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 818 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 819 numLabels = PetscMax(numLabels, 10); 820 numColors = 10; 821 numLColors = 10; 822 ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 823 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 824 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL);CHKERRQ(ierr); 825 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 826 for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 827 for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 828 n = 4; 829 ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg);CHKERRQ(ierr); 830 if (flg && n != dim+1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 831 ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg);CHKERRQ(ierr); 832 if (flg && n != dim+1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1); 833 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 834 if (!useLabels) numLabels = 0; 835 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 836 if (!useColors) { 837 numColors = 3; 838 for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 839 } 840 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 841 if (!useColors) { 842 numLColors = 4; 843 for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 844 } 845 ierr = PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg);CHKERRQ(ierr); 846 plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 847 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg);CHKERRQ(ierr); 848 if (flg && plotEdges && depth < dim) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 849 if (depth < dim) plotEdges = PETSC_FALSE; 850 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL);CHKERRQ(ierr); 851 852 /* filter points with labelvalue != labeldefaultvalue */ 853 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 854 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 855 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 856 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 857 if (lflg) { 858 DMLabel lbl; 859 860 ierr = DMGetLabel(dm, lname, &lbl);CHKERRQ(ierr); 861 if (lbl) { 862 PetscInt val, defval; 863 864 ierr = DMLabelGetDefaultValue(lbl, &defval);CHKERRQ(ierr); 865 ierr = PetscBTCreate(pEnd-pStart, &wp);CHKERRQ(ierr); 866 for (c = pStart; c < pEnd; c++) { 867 PetscInt *closure = NULL; 868 PetscInt closureSize; 869 870 ierr = DMLabelGetValue(lbl, c, &val);CHKERRQ(ierr); 871 if (val == defval) continue; 872 873 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 874 for (p = 0; p < closureSize*2; p += 2) { 875 ierr = PetscBTSet(wp, closure[p] - pStart);CHKERRQ(ierr); 876 } 877 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 878 } 879 } 880 } 881 882 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 883 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 884 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 885 ierr = PetscViewerASCIIPrintf(viewer, "\ 886 \\documentclass[tikz]{standalone}\n\n\ 887 \\usepackage{pgflibraryshapes}\n\ 888 \\usetikzlibrary{backgrounds}\n\ 889 \\usetikzlibrary{arrows}\n\ 890 \\begin{document}\n");CHKERRQ(ierr); 891 if (size > 1) { 892 ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 893 for (p = 0; p < size; ++p) { 894 if (p > 0 && p == size-1) { 895 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 896 } else if (p > 0) { 897 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 898 } 899 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 900 } 901 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 902 } 903 if (drawHasse) { 904 PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart)); 905 906 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%D}\n", vStart);CHKERRQ(ierr); 907 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%D}\n", vEnd-1);CHKERRQ(ierr); 908 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%D}\n", vEnd-vStart);CHKERRQ(ierr); 909 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.);CHKERRQ(ierr); 910 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%D}\n", eStart);CHKERRQ(ierr); 911 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%D}\n", eEnd-1);CHKERRQ(ierr); 912 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.);CHKERRQ(ierr); 913 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%D}\n", eEnd-eStart);CHKERRQ(ierr); 914 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%D}\n", cStart);CHKERRQ(ierr); 915 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%D}\n", cEnd-1);CHKERRQ(ierr); 916 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%D}\n", cEnd-cStart);CHKERRQ(ierr); 917 ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.);CHKERRQ(ierr); 918 } 919 ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale);CHKERRQ(ierr); 920 921 /* Plot vertices */ 922 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 923 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 924 for (v = vStart; v < vEnd; ++v) { 925 PetscInt off, dof, d; 926 PetscBool isLabeled = PETSC_FALSE; 927 928 if (wp && !PetscBTLookup(wp,v - pStart)) continue; 929 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 930 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 931 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 932 if (PetscUnlikely(dof > 3)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 933 for (d = 0; d < dof; ++d) { 934 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 935 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 936 } 937 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 938 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 939 for (d = 0; d < dof; ++d) { 940 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 941 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]);CHKERRQ(ierr); 942 } 943 if (drawHasse) color = colors[0%numColors]; 944 else color = colors[rank%numColors]; 945 for (l = 0; l < numLabels; ++l) { 946 PetscInt val; 947 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 948 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 949 } 950 if (drawNumbers[0]) { 951 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 952 } else if (drawColors[0]) { 953 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 954 } else { 955 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", v, rank);CHKERRQ(ierr); 956 } 957 } 958 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 959 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 960 /* Plot edges */ 961 if (plotEdges) { 962 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 963 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 964 for (e = eStart; e < eEnd; ++e) { 965 const PetscInt *cone; 966 PetscInt coneSize, offA, offB, dof, d; 967 968 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 969 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 970 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 971 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 972 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 973 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 974 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 975 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 976 for (d = 0; d < dof; ++d) { 977 tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 978 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 979 } 980 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 981 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 982 for (d = 0; d < dof; ++d) { 983 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 984 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr); 985 } 986 if (drawHasse) color = colors[1%numColors]; 987 else color = colors[rank%numColors]; 988 for (l = 0; l < numLabels; ++l) { 989 PetscInt val; 990 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 991 if (val >= 0) {color = lcolors[l%numLColors]; break;} 992 } 993 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 994 } 995 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 996 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 997 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 998 } 999 /* Plot cells */ 1000 if (dim == 3 || !drawNumbers[1]) { 1001 for (e = eStart; e < eEnd; ++e) { 1002 const PetscInt *cone; 1003 1004 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 1005 color = colors[rank%numColors]; 1006 for (l = 0; l < numLabels; ++l) { 1007 PetscInt val; 1008 ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 1009 if (val >= 0) {color = lcolors[l%numLColors]; break;} 1010 } 1011 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 1012 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 1013 } 1014 } else { 1015 DMPolytopeType ct; 1016 1017 /* Drawing a 2D polygon */ 1018 for (c = cStart; c < cEnd; ++c) { 1019 if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1020 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 1021 if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || 1022 ct == DM_POLYTOPE_TRI_PRISM_TENSOR || 1023 ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 1024 const PetscInt *cone; 1025 PetscInt coneSize, e; 1026 1027 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 1028 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 1029 for (e = 0; e < coneSize; ++e) { 1030 const PetscInt *econe; 1031 1032 ierr = DMPlexGetCone(dm, cone[e], &econe);CHKERRQ(ierr); 1033 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d) -- (%D_%d);\n", colors[rank%numColors], econe[0], rank, cone[e], rank, econe[1], rank);CHKERRQ(ierr); 1034 } 1035 } else { 1036 PetscInt *closure = NULL; 1037 PetscInt closureSize, Nv = 0, v; 1038 1039 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1040 for (p = 0; p < closureSize*2; p += 2) { 1041 const PetscInt point = closure[p]; 1042 1043 if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1044 } 1045 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 1046 for (v = 0; v <= Nv; ++v) { 1047 const PetscInt vertex = closure[v%Nv]; 1048 1049 if (v > 0) { 1050 if (plotEdges) { 1051 const PetscInt *edge; 1052 PetscInt endpoints[2], ne; 1053 1054 endpoints[0] = closure[v-1]; endpoints[1] = vertex; 1055 ierr = DMPlexGetJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr); 1056 if (ne != 1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %D, %D", endpoints[0], endpoints[1]); 1057 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d) -- ", edge[0], rank);CHKERRQ(ierr); 1058 ierr = DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr); 1059 } else { 1060 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr); 1061 } 1062 } 1063 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", vertex, rank);CHKERRQ(ierr); 1064 } 1065 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ";\n");CHKERRQ(ierr); 1066 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1067 } 1068 } 1069 } 1070 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1071 for (c = cStart; c < cEnd; ++c) { 1072 double ccoords[3] = {0.0, 0.0, 0.0}; 1073 PetscBool isLabeled = PETSC_FALSE; 1074 PetscInt *closure = NULL; 1075 PetscInt closureSize, dof, d, n = 0; 1076 1077 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 1078 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1079 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 1080 for (p = 0; p < closureSize*2; p += 2) { 1081 const PetscInt point = closure[p]; 1082 PetscInt off; 1083 1084 if ((point < vStart) || (point >= vEnd)) continue; 1085 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 1086 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 1087 for (d = 0; d < dof; ++d) { 1088 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 1089 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1090 } 1091 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 1092 if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 1093 for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 1094 ++n; 1095 } 1096 for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 1097 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1098 for (d = 0; d < dof; ++d) { 1099 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 1100 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]);CHKERRQ(ierr); 1101 } 1102 if (drawHasse) color = colors[depth%numColors]; 1103 else color = colors[rank%numColors]; 1104 for (l = 0; l < numLabels; ++l) { 1105 PetscInt val; 1106 ierr = DMGetLabelValue(dm, names[l], c, &val);CHKERRQ(ierr); 1107 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 1108 } 1109 if (drawNumbers[dim]) { 1110 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c);CHKERRQ(ierr); 1111 } else if (drawColors[dim]) { 1112 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 1113 } else { 1114 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", c, rank);CHKERRQ(ierr); 1115 } 1116 } 1117 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1118 if (drawHasse) { 1119 color = colors[depth%numColors]; 1120 ierr = PetscViewerASCIIPrintf(viewer, "%% Cells\n");CHKERRQ(ierr); 1121 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n");CHKERRQ(ierr); 1122 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1123 ierr = PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color);CHKERRQ(ierr); 1124 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1125 1126 color = colors[1%numColors]; 1127 ierr = PetscViewerASCIIPrintf(viewer, "%% Edges\n");CHKERRQ(ierr); 1128 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n");CHKERRQ(ierr); 1129 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1130 ierr = PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color);CHKERRQ(ierr); 1131 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1132 1133 color = colors[0%numColors]; 1134 ierr = PetscViewerASCIIPrintf(viewer, "%% Vertices\n");CHKERRQ(ierr); 1135 ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n");CHKERRQ(ierr); 1136 ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr); 1137 ierr = PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color);CHKERRQ(ierr); 1138 ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr); 1139 1140 for (p = pStart; p < pEnd; ++p) { 1141 const PetscInt *cone; 1142 PetscInt coneSize, cp; 1143 1144 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1145 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1146 for (cp = 0; cp < coneSize; ++cp) { 1147 ierr = PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%D_%d) -- (%D_%d);\n", cone[cp], rank, p, rank);CHKERRQ(ierr); 1148 } 1149 } 1150 } 1151 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1152 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 1153 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 1154 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 1155 for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 1156 for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 1157 for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 1158 ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 1159 ierr = PetscBTDestroy(&wp);CHKERRQ(ierr); 1160 } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 1161 Vec cown,acown; 1162 VecScatter sct; 1163 ISLocalToGlobalMapping g2l; 1164 IS gid,acis; 1165 MPI_Comm comm,ncomm = MPI_COMM_NULL; 1166 MPI_Group ggroup,ngroup; 1167 PetscScalar *array,nid; 1168 const PetscInt *idxs; 1169 PetscInt *idxs2,*start,*adjacency,*work; 1170 PetscInt64 lm[3],gm[3]; 1171 PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 1172 PetscMPIInt d1,d2,rank; 1173 1174 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1175 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 1176 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1177 ierr = MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm);CHKERRMPI(ierr); 1178 #endif 1179 if (ncomm != MPI_COMM_NULL) { 1180 ierr = MPI_Comm_group(comm,&ggroup);CHKERRMPI(ierr); 1181 ierr = MPI_Comm_group(ncomm,&ngroup);CHKERRMPI(ierr); 1182 d1 = 0; 1183 ierr = MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2);CHKERRMPI(ierr); 1184 nid = d2; 1185 ierr = MPI_Group_free(&ggroup);CHKERRMPI(ierr); 1186 ierr = MPI_Group_free(&ngroup);CHKERRMPI(ierr); 1187 ierr = MPI_Comm_free(&ncomm);CHKERRMPI(ierr); 1188 } else nid = 0.0; 1189 1190 /* Get connectivity */ 1191 ierr = DMPlexGetVTKCellHeight(dm,&cellHeight);CHKERRQ(ierr); 1192 ierr = DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid);CHKERRQ(ierr); 1193 1194 /* filter overlapped local cells */ 1195 ierr = DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd);CHKERRQ(ierr); 1196 ierr = ISGetIndices(gid,&idxs);CHKERRQ(ierr); 1197 ierr = ISGetLocalSize(gid,&cum);CHKERRQ(ierr); 1198 ierr = PetscMalloc1(cum,&idxs2);CHKERRQ(ierr); 1199 for (c = cStart, cum = 0; c < cEnd; c++) { 1200 if (idxs[c-cStart] < 0) continue; 1201 idxs2[cum++] = idxs[c-cStart]; 1202 } 1203 ierr = ISRestoreIndices(gid,&idxs);CHKERRQ(ierr); 1204 if (numVertices != cum) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum); 1205 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1206 ierr = ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid);CHKERRQ(ierr); 1207 1208 /* support for node-aware cell locality */ 1209 ierr = ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis);CHKERRQ(ierr); 1210 ierr = VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown);CHKERRQ(ierr); 1211 ierr = VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown);CHKERRQ(ierr); 1212 ierr = VecGetArray(cown,&array);CHKERRQ(ierr); 1213 for (c = 0; c < numVertices; c++) array[c] = nid; 1214 ierr = VecRestoreArray(cown,&array);CHKERRQ(ierr); 1215 ierr = VecScatterCreate(cown,acis,acown,NULL,&sct);CHKERRQ(ierr); 1216 ierr = VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1217 ierr = VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1218 ierr = ISDestroy(&acis);CHKERRQ(ierr); 1219 ierr = VecScatterDestroy(&sct);CHKERRQ(ierr); 1220 ierr = VecDestroy(&cown);CHKERRQ(ierr); 1221 1222 /* compute edgeCut */ 1223 for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 1224 ierr = PetscMalloc1(cum,&work);CHKERRQ(ierr); 1225 ierr = ISLocalToGlobalMappingCreateIS(gid,&g2l);CHKERRQ(ierr); 1226 ierr = ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 1227 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1228 ierr = VecGetArray(acown,&array);CHKERRQ(ierr); 1229 for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 1230 PetscInt totl; 1231 1232 totl = start[c+1]-start[c]; 1233 ierr = ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work);CHKERRQ(ierr); 1234 for (i = 0; i < totl; i++) { 1235 if (work[i] < 0) { 1236 ect += 1; 1237 ectn += (array[i + start[c]] != nid) ? 0 : 1; 1238 } 1239 } 1240 } 1241 ierr = PetscFree(work);CHKERRQ(ierr); 1242 ierr = VecRestoreArray(acown,&array);CHKERRQ(ierr); 1243 lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 1244 lm[1] = -numVertices; 1245 ierr = MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm);CHKERRMPI(ierr); 1246 ierr = PetscViewerASCIIPrintf(viewer," Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]);CHKERRQ(ierr); 1247 lm[0] = ect; /* edgeCut */ 1248 lm[1] = ectn; /* node-aware edgeCut */ 1249 lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 1250 ierr = MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr); 1251 ierr = PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]);CHKERRQ(ierr); 1252 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1253 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),gm[0] ? ((double)(gm[1]))/((double)gm[0]) : 1.);CHKERRQ(ierr); 1254 #else 1255 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0);CHKERRQ(ierr); 1256 #endif 1257 ierr = ISLocalToGlobalMappingDestroy(&g2l);CHKERRQ(ierr); 1258 ierr = PetscFree(start);CHKERRQ(ierr); 1259 ierr = PetscFree(adjacency);CHKERRQ(ierr); 1260 ierr = VecDestroy(&acown);CHKERRQ(ierr); 1261 } else { 1262 const char *name; 1263 PetscInt *sizes, *hybsizes, *ghostsizes; 1264 PetscInt locDepth, depth, cellHeight, dim, d; 1265 PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1266 PetscInt numLabels, l; 1267 DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1268 MPI_Comm comm; 1269 PetscMPIInt size, rank; 1270 1271 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1272 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1273 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1274 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1275 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 1276 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 1277 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1278 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1279 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 1280 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 1281 ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRMPI(ierr); 1282 ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr); 1283 gcNum = gcEnd - gcStart; 1284 ierr = PetscCalloc3(size,&sizes,size,&hybsizes,size,&ghostsizes);CHKERRQ(ierr); 1285 for (d = 0; d <= depth; d++) { 1286 PetscInt Nc[2] = {0, 0}, ict; 1287 1288 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 1289 if (pStart < pEnd) {ierr = DMPlexGetCellType(dm, pStart, &ct0);CHKERRQ(ierr);} 1290 ict = ct0; 1291 ierr = MPI_Bcast(&ict, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1292 ct0 = (DMPolytopeType) ict; 1293 for (p = pStart; p < pEnd; ++p) { 1294 DMPolytopeType ct; 1295 1296 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 1297 if (ct == ct0) ++Nc[0]; 1298 else ++Nc[1]; 1299 } 1300 ierr = MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1301 ierr = MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1302 if (d == depth) {ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);} 1303 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", (depth == 1) && d ? dim : d);CHKERRQ(ierr); 1304 for (p = 0; p < size; ++p) { 1305 if (rank == 0) { 1306 ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]);CHKERRQ(ierr); 1307 if (hybsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]);CHKERRQ(ierr);} 1308 if (ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);} 1309 } 1310 } 1311 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 1312 } 1313 ierr = PetscFree3(sizes,hybsizes,ghostsizes);CHKERRQ(ierr); 1314 { 1315 const PetscReal *maxCell; 1316 const PetscReal *L; 1317 const DMBoundaryType *bd; 1318 PetscBool per, localized; 1319 1320 ierr = DMGetPeriodicity(dm, &per, &maxCell, &L, &bd);CHKERRQ(ierr); 1321 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 1322 if (per) { 1323 ierr = PetscViewerASCIIPrintf(viewer, "Periodic mesh (");CHKERRQ(ierr); 1324 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1325 for (d = 0; d < dim; ++d) { 1326 if (bd && d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1327 if (bd) {ierr = PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]]);CHKERRQ(ierr);} 1328 } 1329 ierr = PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized");CHKERRQ(ierr); 1330 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1331 } 1332 } 1333 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 1334 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 1335 for (l = 0; l < numLabels; ++l) { 1336 DMLabel label; 1337 const char *name; 1338 IS valueIS; 1339 const PetscInt *values; 1340 PetscInt numValues, v; 1341 1342 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 1343 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1344 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 1345 ierr = PetscViewerASCIIPrintf(viewer, " %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr); 1346 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 1347 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 1348 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1349 for (v = 0; v < numValues; ++v) { 1350 PetscInt size; 1351 1352 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 1353 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1354 ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr); 1355 } 1356 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 1357 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1358 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 1359 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 1360 } 1361 { 1362 char **labelNames; 1363 PetscInt Nl = numLabels; 1364 PetscBool flg; 1365 1366 ierr = PetscMalloc1(Nl, &labelNames);CHKERRQ(ierr); 1367 ierr = PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg);CHKERRQ(ierr); 1368 for (l = 0; l < Nl; ++l) { 1369 DMLabel label; 1370 1371 ierr = DMHasLabel(dm, labelNames[l], &flg);CHKERRQ(ierr); 1372 if (flg) { 1373 ierr = DMGetLabel(dm, labelNames[l], &label);CHKERRQ(ierr); 1374 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 1375 } 1376 ierr = PetscFree(labelNames[l]);CHKERRQ(ierr); 1377 } 1378 ierr = PetscFree(labelNames);CHKERRQ(ierr); 1379 } 1380 /* If no fields are specified, people do not want to see adjacency */ 1381 if (dm->Nf) { 1382 PetscInt f; 1383 1384 for (f = 0; f < dm->Nf; ++f) { 1385 const char *name; 1386 1387 ierr = PetscObjectGetName(dm->fields[f].disc, &name);CHKERRQ(ierr); 1388 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Field %s:\n", name);CHKERRQ(ierr);} 1389 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1390 if (dm->fields[f].label) {ierr = DMLabelView(dm->fields[f].label, viewer);CHKERRQ(ierr);} 1391 if (dm->fields[f].adjacency[0]) { 1392 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n");CHKERRQ(ierr);} 1393 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM\n");CHKERRQ(ierr);} 1394 } else { 1395 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FEM\n");CHKERRQ(ierr);} 1396 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n");CHKERRQ(ierr);} 1397 } 1398 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1399 } 1400 } 1401 ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr); 1402 if (cdm) { 1403 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1404 ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr); 1405 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1406 } 1407 } 1408 PetscFunctionReturn(0); 1409 } 1410 1411 static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1412 { 1413 DMPolytopeType ct; 1414 PetscMPIInt rank; 1415 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 if (ishdf5) { 1684 #if defined(PETSC_HAVE_HDF5) 1685 PetscViewerFormat format; 1686 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1687 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1688 IS globalPointNumbering; 1689 1690 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1691 ierr = DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1692 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1693 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 1694 #else 1695 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1696 #endif 1697 } 1698 PetscFunctionReturn(0); 1699 } 1700 1701 /*@ 1702 DMPlexCoordinatesView - Saves DMPlex coordinates into a file 1703 1704 Collective on DM 1705 1706 Input Parameters: 1707 + dm - The DM whose coordinates are to be saved 1708 - viewer - The PetscViewer for saving 1709 1710 Level: advanced 1711 1712 .seealso: DMView(), DMPlexTopologyView(), DMPlexLabelsView(), DMPlexCoordinatesLoad() 1713 @*/ 1714 PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 1715 { 1716 PetscBool ishdf5; 1717 PetscErrorCode ierr; 1718 1719 PetscFunctionBegin; 1720 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1721 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1722 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1723 if (ishdf5) { 1724 #if defined(PETSC_HAVE_HDF5) 1725 PetscViewerFormat format; 1726 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1727 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1728 ierr = DMPlexCoordinatesView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1729 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1730 #else 1731 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1732 #endif 1733 } 1734 PetscFunctionReturn(0); 1735 } 1736 1737 /*@ 1738 DMPlexLabelsView - Saves DMPlex labels into a file 1739 1740 Collective on DM 1741 1742 Input Parameters: 1743 + dm - The DM whose labels are to be saved 1744 - viewer - The PetscViewer for saving 1745 1746 Level: advanced 1747 1748 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsLoad() 1749 @*/ 1750 PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1751 { 1752 PetscBool ishdf5; 1753 PetscErrorCode ierr; 1754 1755 PetscFunctionBegin; 1756 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1757 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1758 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1759 if (ishdf5) { 1760 #if defined(PETSC_HAVE_HDF5) 1761 IS globalPointNumbering; 1762 PetscViewerFormat format; 1763 1764 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1765 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1766 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1767 ierr = DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1768 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1769 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1770 #else 1771 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1772 #endif 1773 } 1774 PetscFunctionReturn(0); 1775 } 1776 1777 /*@ 1778 DMPlexSectionView - Saves a section associated with a DMPlex 1779 1780 Collective on DM 1781 1782 Input Parameters: 1783 + dm - The DM that contains the topology on which the section to be saved is defined 1784 . viewer - The PetscViewer for saving 1785 - sectiondm - The DM that contains the section to be saved 1786 1787 Level: advanced 1788 1789 Notes: 1790 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. 1791 1792 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. 1793 1794 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexGlobalVectorView(), DMPlexLocalVectorView(), PetscSectionView(), DMPlexSectionLoad() 1795 @*/ 1796 PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1797 { 1798 PetscBool ishdf5; 1799 PetscErrorCode ierr; 1800 1801 PetscFunctionBegin; 1802 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1803 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1804 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1805 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 1806 if (ishdf5) { 1807 #if defined(PETSC_HAVE_HDF5) 1808 ierr = DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm);CHKERRQ(ierr); 1809 #else 1810 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1811 #endif 1812 } 1813 PetscFunctionReturn(0); 1814 } 1815 1816 /*@ 1817 DMPlexGlobalVectorView - Saves a global vector 1818 1819 Collective on DM 1820 1821 Input Parameters: 1822 + dm - The DM that represents the topology 1823 . viewer - The PetscViewer to save data with 1824 . sectiondm - The DM that contains the global section on which vec is defined 1825 - vec - The global vector to be saved 1826 1827 Level: advanced 1828 1829 Notes: 1830 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. 1831 1832 Typical calling sequence 1833 $ DMCreate(PETSC_COMM_WORLD, &dm); 1834 $ DMSetType(dm, DMPLEX); 1835 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1836 $ DMClone(dm, §iondm); 1837 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1838 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1839 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1840 $ PetscSectionSetChart(section, pStart, pEnd); 1841 $ PetscSectionSetUp(section); 1842 $ DMSetLocalSection(sectiondm, section); 1843 $ PetscSectionDestroy(§ion); 1844 $ DMGetGlobalVector(sectiondm, &vec); 1845 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1846 $ DMPlexTopologyView(dm, viewer); 1847 $ DMPlexSectionView(dm, viewer, sectiondm); 1848 $ DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 1849 $ DMRestoreGlobalVector(sectiondm, &vec); 1850 $ DMDestroy(§iondm); 1851 $ DMDestroy(&dm); 1852 1853 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexLocalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1854 @*/ 1855 PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1856 { 1857 PetscBool ishdf5; 1858 PetscErrorCode ierr; 1859 1860 PetscFunctionBegin; 1861 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1862 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1863 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1864 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1865 /* Check consistency */ 1866 { 1867 PetscSection section; 1868 PetscBool includesConstraints; 1869 PetscInt m, m1; 1870 1871 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1872 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 1873 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1874 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1875 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1876 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 1877 } 1878 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1879 if (ishdf5) { 1880 #if defined(PETSC_HAVE_HDF5) 1881 ierr = DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1882 #else 1883 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1884 #endif 1885 } 1886 PetscFunctionReturn(0); 1887 } 1888 1889 /*@ 1890 DMPlexLocalVectorView - Saves a local vector 1891 1892 Collective on DM 1893 1894 Input Parameters: 1895 + dm - The DM that represents the topology 1896 . viewer - The PetscViewer to save data with 1897 . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm 1898 - vec - The local vector to be saved 1899 1900 Level: advanced 1901 1902 Notes: 1903 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. 1904 1905 Typical calling sequence 1906 $ DMCreate(PETSC_COMM_WORLD, &dm); 1907 $ DMSetType(dm, DMPLEX); 1908 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1909 $ DMClone(dm, §iondm); 1910 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1911 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1912 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1913 $ PetscSectionSetChart(section, pStart, pEnd); 1914 $ PetscSectionSetUp(section); 1915 $ DMSetLocalSection(sectiondm, section); 1916 $ DMGetLocalVector(sectiondm, &vec); 1917 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1918 $ DMPlexTopologyView(dm, viewer); 1919 $ DMPlexSectionView(dm, viewer, sectiondm); 1920 $ DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 1921 $ DMRestoreLocalVector(sectiondm, &vec); 1922 $ DMDestroy(§iondm); 1923 $ DMDestroy(&dm); 1924 1925 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexGlobalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1926 @*/ 1927 PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1928 { 1929 PetscBool ishdf5; 1930 PetscErrorCode ierr; 1931 1932 PetscFunctionBegin; 1933 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1934 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1935 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1936 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1937 /* Check consistency */ 1938 { 1939 PetscSection section; 1940 PetscBool includesConstraints; 1941 PetscInt m, m1; 1942 1943 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1944 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 1945 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1946 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1947 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1948 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 1949 } 1950 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1951 if (ishdf5) { 1952 #if defined(PETSC_HAVE_HDF5) 1953 ierr = DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1954 #else 1955 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1956 #endif 1957 } 1958 PetscFunctionReturn(0); 1959 } 1960 1961 PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 1962 { 1963 PetscBool ishdf5; 1964 PetscErrorCode ierr; 1965 1966 PetscFunctionBegin; 1967 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1968 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1969 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1970 if (ishdf5) { 1971 #if defined(PETSC_HAVE_HDF5) 1972 PetscViewerFormat format; 1973 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1974 if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 1975 ierr = DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer);CHKERRQ(ierr); 1976 } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1977 ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1978 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1979 PetscFunctionReturn(0); 1980 #else 1981 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1982 #endif 1983 } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 1984 } 1985 1986 /*@ 1987 DMPlexTopologyLoad - Loads a topology into a DMPlex 1988 1989 Collective on DM 1990 1991 Input Parameters: 1992 + dm - The DM into which the topology is loaded 1993 - viewer - The PetscViewer for the saved topology 1994 1995 Output Parameters: 1996 . 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 1997 1998 Level: advanced 1999 2000 .seealso: DMLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2001 @*/ 2002 PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2003 { 2004 PetscBool ishdf5; 2005 PetscErrorCode ierr; 2006 2007 PetscFunctionBegin; 2008 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2009 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2010 if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 2011 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2012 if (ishdf5) { 2013 #if defined(PETSC_HAVE_HDF5) 2014 PetscViewerFormat format; 2015 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2016 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2017 ierr = DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 2018 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2019 #else 2020 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2021 #endif 2022 } 2023 PetscFunctionReturn(0); 2024 } 2025 2026 /*@ 2027 DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 2028 2029 Collective on DM 2030 2031 Input Parameters: 2032 + dm - The DM into which the coordinates are loaded 2033 - viewer - The PetscViewer for the saved coordinates 2034 2035 Level: advanced 2036 2037 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2038 @*/ 2039 PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer) 2040 { 2041 PetscBool ishdf5; 2042 PetscErrorCode ierr; 2043 2044 PetscFunctionBegin; 2045 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2046 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2047 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2048 if (ishdf5) { 2049 #if defined(PETSC_HAVE_HDF5) 2050 PetscViewerFormat format; 2051 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2052 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2053 ierr = DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 2054 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2055 #else 2056 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2057 #endif 2058 } 2059 PetscFunctionReturn(0); 2060 } 2061 2062 /*@ 2063 DMPlexLabelsLoad - Loads labels into a DMPlex 2064 2065 Collective on DM 2066 2067 Input Parameters: 2068 + dm - The DM into which the labels are loaded 2069 - viewer - The PetscViewer for the saved labels 2070 2071 Level: advanced 2072 2073 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 2074 @*/ 2075 PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer) 2076 { 2077 PetscBool ishdf5; 2078 PetscErrorCode ierr; 2079 2080 PetscFunctionBegin; 2081 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2082 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2083 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 2084 if (ishdf5) { 2085 #if defined(PETSC_HAVE_HDF5) 2086 PetscViewerFormat format; 2087 2088 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 2089 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 2090 ierr = DMPlexLabelsLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 2091 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2092 #else 2093 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2094 #endif 2095 } 2096 PetscFunctionReturn(0); 2097 } 2098 2099 /*@ 2100 DMPlexSectionLoad - Loads section into a DMPlex 2101 2102 Collective on DM 2103 2104 Input Parameters: 2105 + dm - The DM that represents the topology 2106 . viewer - The PetscViewer that represents the on-disk section (sectionA) 2107 . sectiondm - The DM into which the on-disk section (sectionA) is migrated 2108 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 2109 2110 Output Parameters 2111 + 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) 2112 - 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) 2113 2114 Level: advanced 2115 2116 Notes: 2117 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. 2118 2119 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. 2120 2121 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. 2122 2123 Example using 2 processes: 2124 $ NX (number of points on dm): 4 2125 $ sectionA : the on-disk section 2126 $ vecA : a vector associated with sectionA 2127 $ sectionB : sectiondm's local section constructed in this function 2128 $ vecB (local) : a vector associated with sectiondm's local section 2129 $ vecB (global) : a vector associated with sectiondm's global section 2130 $ 2131 $ rank 0 rank 1 2132 $ vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2133 $ sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2134 $ sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2135 $ sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2136 $ [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2137 $ sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2138 $ sectionB->atlasDof : 1 0 1 | 1 3 2139 $ sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2140 $ vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2141 $ vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2142 $ 2143 $ where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2144 2145 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad(), PetscSectionLoad(), DMPlexSectionView() 2146 @*/ 2147 PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2148 { 2149 PetscBool ishdf5; 2150 PetscErrorCode ierr; 2151 2152 PetscFunctionBegin; 2153 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2154 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2155 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2156 PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 2157 if (globalDofSF) PetscValidPointer(globalDofSF, 5); 2158 if (localDofSF) PetscValidPointer(localDofSF, 6); 2159 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2160 if (ishdf5) { 2161 #if defined(PETSC_HAVE_HDF5) 2162 ierr = DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF);CHKERRQ(ierr); 2163 #else 2164 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2165 #endif 2166 } 2167 PetscFunctionReturn(0); 2168 } 2169 2170 /*@ 2171 DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 2172 2173 Collective on DM 2174 2175 Input Parameters: 2176 + dm - The DM that represents the topology 2177 . viewer - The PetscViewer that represents the on-disk vector data 2178 . sectiondm - The DM that contains the global section on which vec is defined 2179 . sf - The SF that migrates the on-disk vector data into vec 2180 - vec - The global vector to set values of 2181 2182 Level: advanced 2183 2184 Notes: 2185 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. 2186 2187 Typical calling sequence 2188 $ DMCreate(PETSC_COMM_WORLD, &dm); 2189 $ DMSetType(dm, DMPLEX); 2190 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2191 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2192 $ DMClone(dm, §iondm); 2193 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2194 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2195 $ DMGetGlobalVector(sectiondm, &vec); 2196 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2197 $ DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2198 $ DMRestoreGlobalVector(sectiondm, &vec); 2199 $ PetscSFDestroy(&gsf); 2200 $ PetscSFDestroy(&sfX); 2201 $ DMDestroy(§iondm); 2202 $ DMDestroy(&dm); 2203 2204 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexLocalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2205 @*/ 2206 PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2207 { 2208 PetscBool ishdf5; 2209 PetscErrorCode ierr; 2210 2211 PetscFunctionBegin; 2212 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2213 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2214 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2215 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2216 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2217 /* Check consistency */ 2218 { 2219 PetscSection section; 2220 PetscBool includesConstraints; 2221 PetscInt m, m1; 2222 2223 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2224 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 2225 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2226 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2227 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2228 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 2229 } 2230 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2231 if (ishdf5) { 2232 #if defined(PETSC_HAVE_HDF5) 2233 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2234 #else 2235 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2236 #endif 2237 } 2238 PetscFunctionReturn(0); 2239 } 2240 2241 /*@ 2242 DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 2243 2244 Collective on DM 2245 2246 Input Parameters: 2247 + dm - The DM that represents the topology 2248 . viewer - The PetscViewer that represents the on-disk vector data 2249 . sectiondm - The DM that contains the local section on which vec is defined 2250 . sf - The SF that migrates the on-disk vector data into vec 2251 - vec - The local vector to set values of 2252 2253 Level: advanced 2254 2255 Notes: 2256 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. 2257 2258 Typical calling sequence 2259 $ DMCreate(PETSC_COMM_WORLD, &dm); 2260 $ DMSetType(dm, DMPLEX); 2261 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2262 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2263 $ DMClone(dm, §iondm); 2264 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2265 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2266 $ DMGetLocalVector(sectiondm, &vec); 2267 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2268 $ DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2269 $ DMRestoreLocalVector(sectiondm, &vec); 2270 $ PetscSFDestroy(&lsf); 2271 $ PetscSFDestroy(&sfX); 2272 $ DMDestroy(§iondm); 2273 $ DMDestroy(&dm); 2274 2275 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexGlobalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2276 @*/ 2277 PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2278 { 2279 PetscBool ishdf5; 2280 PetscErrorCode ierr; 2281 2282 PetscFunctionBegin; 2283 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2284 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2285 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2286 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2287 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2288 /* Check consistency */ 2289 { 2290 PetscSection section; 2291 PetscBool includesConstraints; 2292 PetscInt m, m1; 2293 2294 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2295 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 2296 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2297 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2298 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2299 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 2300 } 2301 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2302 if (ishdf5) { 2303 #if defined(PETSC_HAVE_HDF5) 2304 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2305 #else 2306 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2307 #endif 2308 } 2309 PetscFunctionReturn(0); 2310 } 2311 2312 PetscErrorCode DMDestroy_Plex(DM dm) 2313 { 2314 DM_Plex *mesh = (DM_Plex*) dm->data; 2315 PetscErrorCode ierr; 2316 2317 PetscFunctionBegin; 2318 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr); 2319 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr); 2320 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL);CHKERRQ(ierr); 2321 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL);CHKERRQ(ierr); 2322 if (--mesh->refct > 0) PetscFunctionReturn(0); 2323 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 2324 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 2325 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 2326 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 2327 ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr); 2328 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 2329 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 2330 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 2331 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 2332 ierr = PetscFree(mesh->transformType);CHKERRQ(ierr); 2333 ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 2334 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 2335 ierr = ISDestroy(&mesh->subpointIS);CHKERRQ(ierr); 2336 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 2337 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 2338 ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 2339 ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 2340 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 2341 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 2342 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 2343 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 2344 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 2345 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 2346 ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr); 2347 ierr = PetscFree(mesh->neighbors);CHKERRQ(ierr); 2348 if (mesh->metricCtx) { ierr = PetscFree(mesh->metricCtx);CHKERRQ(ierr); } 2349 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 2350 ierr = PetscFree(mesh);CHKERRQ(ierr); 2351 PetscFunctionReturn(0); 2352 } 2353 2354 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2355 { 2356 PetscSection sectionGlobal; 2357 PetscInt bs = -1, mbs; 2358 PetscInt localSize; 2359 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2360 PetscErrorCode ierr; 2361 MatType mtype; 2362 ISLocalToGlobalMapping ltog; 2363 2364 PetscFunctionBegin; 2365 ierr = MatInitializePackage();CHKERRQ(ierr); 2366 mtype = dm->mattype; 2367 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 2368 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 2369 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 2370 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 2371 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 2372 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 2373 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 2374 ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr); 2375 if (mbs > 1) bs = mbs; 2376 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 2377 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 2378 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 2379 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 2380 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 2381 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 2382 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 2383 ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr); 2384 if (!isShell) { 2385 PetscSection subSection; 2386 PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 2387 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *ltogidx, lsize; 2388 PetscInt pStart, pEnd, p, dof, cdof; 2389 2390 /* Set localtoglobalmapping on the matrix for MatSetValuesLocal() to work (it also creates the local matrices in case of MATIS) */ 2391 if (isMatIS) { /* need a different l2g map than the one computed by DMGetLocalToGlobalMapping */ 2392 PetscSection section; 2393 PetscInt size; 2394 2395 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 2396 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 2397 ierr = PetscMalloc1(size,<ogidx);CHKERRQ(ierr); 2398 ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr); 2399 } else { 2400 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 2401 } 2402 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 2403 for (p = pStart, lsize = 0; p < pEnd; ++p) { 2404 PetscInt bdof; 2405 2406 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 2407 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 2408 dof = dof < 0 ? -(dof+1) : dof; 2409 bdof = cdof && (dof-cdof) ? 1 : dof; 2410 if (dof) { 2411 if (bs < 0) {bs = bdof;} 2412 else if (bs != bdof) {bs = 1; if (!isMatIS) break;} 2413 } 2414 if (isMatIS) { 2415 PetscInt loff,c,off; 2416 ierr = PetscSectionGetOffset(subSection, p, &loff);CHKERRQ(ierr); 2417 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 2418 for (c = 0; c < dof-cdof; ++c, ++lsize) ltogidx[loff+c] = off > -1 ? off+c : -(off+1)+c; 2419 } 2420 } 2421 /* Must have same blocksize on all procs (some might have no points) */ 2422 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 2423 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 2424 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 2425 else {bs = bsMinMax[0];} 2426 bs = PetscMax(1,bs); 2427 if (isMatIS) { /* Must reduce indices by blocksize */ 2428 PetscInt l; 2429 2430 lsize = lsize/bs; 2431 if (bs > 1) for (l = 0; l < lsize; ++l) ltogidx[l] = ltogidx[l*bs]/bs; 2432 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, lsize, ltogidx, PETSC_OWN_POINTER, <og);CHKERRQ(ierr); 2433 } 2434 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 2435 if (isMatIS) { 2436 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 2437 } 2438 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 2439 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 2440 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 2441 } 2442 ierr = MatSetDM(*J, dm);CHKERRQ(ierr); 2443 PetscFunctionReturn(0); 2444 } 2445 2446 /*@ 2447 DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2448 2449 Not collective 2450 2451 Input Parameter: 2452 . mesh - The DMPlex 2453 2454 Output Parameters: 2455 . subsection - The subdomain section 2456 2457 Level: developer 2458 2459 .seealso: 2460 @*/ 2461 PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2462 { 2463 DM_Plex *mesh = (DM_Plex*) dm->data; 2464 PetscErrorCode ierr; 2465 2466 PetscFunctionBegin; 2467 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2468 if (!mesh->subdomainSection) { 2469 PetscSection section; 2470 PetscSF sf; 2471 2472 ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr); 2473 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 2474 ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr); 2475 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 2476 } 2477 *subsection = mesh->subdomainSection; 2478 PetscFunctionReturn(0); 2479 } 2480 2481 /*@ 2482 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2483 2484 Not collective 2485 2486 Input Parameter: 2487 . mesh - The DMPlex 2488 2489 Output Parameters: 2490 + pStart - The first mesh point 2491 - pEnd - The upper bound for mesh points 2492 2493 Level: beginner 2494 2495 .seealso: DMPlexCreate(), DMPlexSetChart() 2496 @*/ 2497 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2498 { 2499 DM_Plex *mesh = (DM_Plex*) dm->data; 2500 PetscErrorCode ierr; 2501 2502 PetscFunctionBegin; 2503 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2504 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2505 PetscFunctionReturn(0); 2506 } 2507 2508 /*@ 2509 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2510 2511 Not collective 2512 2513 Input Parameters: 2514 + mesh - The DMPlex 2515 . pStart - The first mesh point 2516 - pEnd - The upper bound for mesh points 2517 2518 Output Parameters: 2519 2520 Level: beginner 2521 2522 .seealso: DMPlexCreate(), DMPlexGetChart() 2523 @*/ 2524 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2525 { 2526 DM_Plex *mesh = (DM_Plex*) dm->data; 2527 PetscErrorCode ierr; 2528 2529 PetscFunctionBegin; 2530 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2531 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2532 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 2533 PetscFunctionReturn(0); 2534 } 2535 2536 /*@ 2537 DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2538 2539 Not collective 2540 2541 Input Parameters: 2542 + mesh - The DMPlex 2543 - p - The point, which must lie in the chart set with DMPlexSetChart() 2544 2545 Output Parameter: 2546 . size - The cone size for point p 2547 2548 Level: beginner 2549 2550 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2551 @*/ 2552 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2553 { 2554 DM_Plex *mesh = (DM_Plex*) dm->data; 2555 PetscErrorCode ierr; 2556 2557 PetscFunctionBegin; 2558 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2559 PetscValidPointer(size, 3); 2560 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2561 PetscFunctionReturn(0); 2562 } 2563 2564 /*@ 2565 DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2566 2567 Not collective 2568 2569 Input Parameters: 2570 + mesh - The DMPlex 2571 . p - The point, which must lie in the chart set with DMPlexSetChart() 2572 - size - The cone size for point p 2573 2574 Output Parameter: 2575 2576 Note: 2577 This should be called after DMPlexSetChart(). 2578 2579 Level: beginner 2580 2581 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 2582 @*/ 2583 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2584 { 2585 DM_Plex *mesh = (DM_Plex*) dm->data; 2586 PetscErrorCode ierr; 2587 2588 PetscFunctionBegin; 2589 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2590 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2591 2592 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 2593 PetscFunctionReturn(0); 2594 } 2595 2596 /*@ 2597 DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2598 2599 Not collective 2600 2601 Input Parameters: 2602 + mesh - The DMPlex 2603 . p - The point, which must lie in the chart set with DMPlexSetChart() 2604 - size - The additional cone size for point p 2605 2606 Output Parameter: 2607 2608 Note: 2609 This should be called after DMPlexSetChart(). 2610 2611 Level: beginner 2612 2613 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 2614 @*/ 2615 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2616 { 2617 DM_Plex *mesh = (DM_Plex*) dm->data; 2618 PetscInt csize; 2619 PetscErrorCode ierr; 2620 2621 PetscFunctionBegin; 2622 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2623 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2624 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 2625 2626 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 2627 PetscFunctionReturn(0); 2628 } 2629 2630 /*@C 2631 DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2632 2633 Not collective 2634 2635 Input Parameters: 2636 + dm - The DMPlex 2637 - p - The point, which must lie in the chart set with DMPlexSetChart() 2638 2639 Output Parameter: 2640 . cone - An array of points which are on the in-edges for point p 2641 2642 Level: beginner 2643 2644 Fortran Notes: 2645 Since it returns an array, this routine is only available in Fortran 90, and you must 2646 include petsc.h90 in your code. 2647 You must also call DMPlexRestoreCone() after you finish using the returned array. 2648 DMPlexRestoreCone() is not needed/available in C. 2649 2650 .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart() 2651 @*/ 2652 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2653 { 2654 DM_Plex *mesh = (DM_Plex*) dm->data; 2655 PetscInt off; 2656 PetscErrorCode ierr; 2657 2658 PetscFunctionBegin; 2659 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2660 PetscValidPointer(cone, 3); 2661 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2662 *cone = &mesh->cones[off]; 2663 PetscFunctionReturn(0); 2664 } 2665 2666 /*@C 2667 DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 2668 2669 Not collective 2670 2671 Input Parameters: 2672 + dm - The DMPlex 2673 - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 2674 2675 Output Parameters: 2676 + pConesSection - PetscSection describing the layout of pCones 2677 - pCones - An array of points which are on the in-edges for the point set p 2678 2679 Level: intermediate 2680 2681 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart() 2682 @*/ 2683 PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 2684 { 2685 PetscSection cs, newcs; 2686 PetscInt *cones; 2687 PetscInt *newarr=NULL; 2688 PetscInt n; 2689 PetscErrorCode ierr; 2690 2691 PetscFunctionBegin; 2692 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 2693 ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr); 2694 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 2695 if (pConesSection) *pConesSection = newcs; 2696 if (pCones) { 2697 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 2698 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr); 2699 } 2700 PetscFunctionReturn(0); 2701 } 2702 2703 /*@ 2704 DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2705 2706 Not collective 2707 2708 Input Parameters: 2709 + dm - The DMPlex 2710 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2711 2712 Output Parameter: 2713 . expandedPoints - An array of vertices recursively expanded from input points 2714 2715 Level: advanced 2716 2717 Notes: 2718 Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2719 There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2720 2721 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth() 2722 @*/ 2723 PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2724 { 2725 IS *expandedPointsAll; 2726 PetscInt depth; 2727 PetscErrorCode ierr; 2728 2729 PetscFunctionBegin; 2730 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2731 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2732 PetscValidPointer(expandedPoints, 3); 2733 ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2734 *expandedPoints = expandedPointsAll[0]; 2735 ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]);CHKERRQ(ierr); 2736 ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2737 PetscFunctionReturn(0); 2738 } 2739 2740 /*@ 2741 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). 2742 2743 Not collective 2744 2745 Input Parameters: 2746 + dm - The DMPlex 2747 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2748 2749 Output Parameters: 2750 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2751 . expandedPoints - (optional) An array of index sets with recursively expanded cones 2752 - sections - (optional) An array of sections which describe mappings from points to their cone points 2753 2754 Level: advanced 2755 2756 Notes: 2757 Like DMPlexGetConeTuple() but recursive. 2758 2759 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. 2760 For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2761 2762 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: 2763 (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2764 (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2765 2766 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2767 @*/ 2768 PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2769 { 2770 const PetscInt *arr0=NULL, *cone=NULL; 2771 PetscInt *arr=NULL, *newarr=NULL; 2772 PetscInt d, depth_, i, n, newn, cn, co, start, end; 2773 IS *expandedPoints_; 2774 PetscSection *sections_; 2775 PetscErrorCode ierr; 2776 2777 PetscFunctionBegin; 2778 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2779 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2780 if (depth) PetscValidIntPointer(depth, 3); 2781 if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2782 if (sections) PetscValidPointer(sections, 5); 2783 ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr); 2784 ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr); 2785 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2786 ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr); 2787 ierr = PetscCalloc1(depth_, §ions_);CHKERRQ(ierr); 2788 arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2789 for (d=depth_-1; d>=0; d--) { 2790 ierr = PetscSectionCreate(PETSC_COMM_SELF, §ions_[d]);CHKERRQ(ierr); 2791 ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr); 2792 for (i=0; i<n; i++) { 2793 ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr); 2794 if (arr[i] >= start && arr[i] < end) { 2795 ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr); 2796 ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr); 2797 } else { 2798 ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr); 2799 } 2800 } 2801 ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr); 2802 ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr); 2803 ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr); 2804 for (i=0; i<n; i++) { 2805 ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr); 2806 ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr); 2807 if (cn > 1) { 2808 ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr); 2809 ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr); 2810 } else { 2811 newarr[co] = arr[i]; 2812 } 2813 } 2814 ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr); 2815 arr = newarr; 2816 n = newn; 2817 } 2818 ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr); 2819 *depth = depth_; 2820 if (expandedPoints) *expandedPoints = expandedPoints_; 2821 else { 2822 for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);} 2823 ierr = PetscFree(expandedPoints_);CHKERRQ(ierr); 2824 } 2825 if (sections) *sections = sections_; 2826 else { 2827 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(§ions_[d]);CHKERRQ(ierr);} 2828 ierr = PetscFree(sections_);CHKERRQ(ierr); 2829 } 2830 PetscFunctionReturn(0); 2831 } 2832 2833 /*@ 2834 DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2835 2836 Not collective 2837 2838 Input Parameters: 2839 + dm - The DMPlex 2840 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2841 2842 Output Parameters: 2843 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2844 . expandedPoints - (optional) An array of recursively expanded cones 2845 - sections - (optional) An array of sections which describe mappings from points to their cone points 2846 2847 Level: advanced 2848 2849 Notes: 2850 See DMPlexGetConeRecursive() for details. 2851 2852 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2853 @*/ 2854 PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2855 { 2856 PetscInt d, depth_; 2857 PetscErrorCode ierr; 2858 2859 PetscFunctionBegin; 2860 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2861 if (depth && *depth != depth_) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2862 if (depth) *depth = 0; 2863 if (expandedPoints) { 2864 for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);} 2865 ierr = PetscFree(*expandedPoints);CHKERRQ(ierr); 2866 } 2867 if (sections) { 2868 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);} 2869 ierr = PetscFree(*sections);CHKERRQ(ierr); 2870 } 2871 PetscFunctionReturn(0); 2872 } 2873 2874 /*@ 2875 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 2876 2877 Not collective 2878 2879 Input Parameters: 2880 + mesh - The DMPlex 2881 . p - The point, which must lie in the chart set with DMPlexSetChart() 2882 - cone - An array of points which are on the in-edges for point p 2883 2884 Output Parameter: 2885 2886 Note: 2887 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2888 2889 Level: beginner 2890 2891 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize() 2892 @*/ 2893 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 2894 { 2895 DM_Plex *mesh = (DM_Plex*) dm->data; 2896 PetscInt pStart, pEnd; 2897 PetscInt dof, off, c; 2898 PetscErrorCode ierr; 2899 2900 PetscFunctionBegin; 2901 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2902 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2903 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2904 if (dof) PetscValidPointer(cone, 3); 2905 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2906 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); 2907 for (c = 0; c < dof; ++c) { 2908 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); 2909 mesh->cones[off+c] = cone[c]; 2910 } 2911 PetscFunctionReturn(0); 2912 } 2913 2914 /*@C 2915 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 2916 2917 Not collective 2918 2919 Input Parameters: 2920 + mesh - The DMPlex 2921 - p - The point, which must lie in the chart set with DMPlexSetChart() 2922 2923 Output Parameter: 2924 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2925 integer giving the prescription for cone traversal. 2926 2927 Level: beginner 2928 2929 Notes: 2930 The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 2931 the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 2932 of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv() 2933 with the identity. 2934 2935 Fortran Notes: 2936 Since it returns an array, this routine is only available in Fortran 90, and you must 2937 include petsc.h90 in your code. 2938 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 2939 DMPlexRestoreConeOrientation() is not needed/available in C. 2940 2941 .seealso: DMPolytopeTypeComposeOrientation(), DMPolytopeTypeComposeOrientationInv(), DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 2942 @*/ 2943 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 2944 { 2945 DM_Plex *mesh = (DM_Plex*) dm->data; 2946 PetscInt off; 2947 PetscErrorCode ierr; 2948 2949 PetscFunctionBegin; 2950 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2951 if (PetscDefined(USE_DEBUG)) { 2952 PetscInt dof; 2953 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2954 if (dof) PetscValidPointer(coneOrientation, 3); 2955 } 2956 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2957 2958 *coneOrientation = &mesh->coneOrientations[off]; 2959 PetscFunctionReturn(0); 2960 } 2961 2962 /*@ 2963 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 2964 2965 Not collective 2966 2967 Input Parameters: 2968 + mesh - The DMPlex 2969 . p - The point, which must lie in the chart set with DMPlexSetChart() 2970 - coneOrientation - An array of orientations 2971 Output Parameter: 2972 2973 Notes: 2974 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2975 2976 The meaning of coneOrientation is detailed in DMPlexGetConeOrientation(). 2977 2978 Level: beginner 2979 2980 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2981 @*/ 2982 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 2983 { 2984 DM_Plex *mesh = (DM_Plex*) dm->data; 2985 PetscInt pStart, pEnd; 2986 PetscInt dof, off, c; 2987 PetscErrorCode ierr; 2988 2989 PetscFunctionBegin; 2990 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2991 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2992 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2993 if (dof) PetscValidPointer(coneOrientation, 3); 2994 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2995 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); 2996 for (c = 0; c < dof; ++c) { 2997 PetscInt cdof, o = coneOrientation[c]; 2998 2999 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 3000 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); 3001 mesh->coneOrientations[off+c] = o; 3002 } 3003 PetscFunctionReturn(0); 3004 } 3005 3006 /*@ 3007 DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 3008 3009 Not collective 3010 3011 Input Parameters: 3012 + mesh - The DMPlex 3013 . p - The point, which must lie in the chart set with DMPlexSetChart() 3014 . conePos - The local index in the cone where the point should be put 3015 - conePoint - The mesh point to insert 3016 3017 Level: beginner 3018 3019 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3020 @*/ 3021 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3022 { 3023 DM_Plex *mesh = (DM_Plex*) dm->data; 3024 PetscInt pStart, pEnd; 3025 PetscInt dof, off; 3026 PetscErrorCode ierr; 3027 3028 PetscFunctionBegin; 3029 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3030 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3031 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); 3032 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); 3033 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3034 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3035 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); 3036 mesh->cones[off+conePos] = conePoint; 3037 PetscFunctionReturn(0); 3038 } 3039 3040 /*@ 3041 DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 3042 3043 Not collective 3044 3045 Input Parameters: 3046 + mesh - The DMPlex 3047 . p - The point, which must lie in the chart set with DMPlexSetChart() 3048 . conePos - The local index in the cone where the point should be put 3049 - coneOrientation - The point orientation to insert 3050 3051 Level: beginner 3052 3053 Notes: 3054 The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation(). 3055 3056 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3057 @*/ 3058 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3059 { 3060 DM_Plex *mesh = (DM_Plex*) dm->data; 3061 PetscInt pStart, pEnd; 3062 PetscInt dof, off; 3063 PetscErrorCode ierr; 3064 3065 PetscFunctionBegin; 3066 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3067 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3068 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); 3069 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3070 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3071 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); 3072 mesh->coneOrientations[off+conePos] = coneOrientation; 3073 PetscFunctionReturn(0); 3074 } 3075 3076 /*@ 3077 DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3078 3079 Not collective 3080 3081 Input Parameters: 3082 + mesh - The DMPlex 3083 - p - The point, which must lie in the chart set with DMPlexSetChart() 3084 3085 Output Parameter: 3086 . size - The support size for point p 3087 3088 Level: beginner 3089 3090 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 3091 @*/ 3092 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3093 { 3094 DM_Plex *mesh = (DM_Plex*) dm->data; 3095 PetscErrorCode ierr; 3096 3097 PetscFunctionBegin; 3098 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3099 PetscValidPointer(size, 3); 3100 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3101 PetscFunctionReturn(0); 3102 } 3103 3104 /*@ 3105 DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3106 3107 Not collective 3108 3109 Input Parameters: 3110 + mesh - The DMPlex 3111 . p - The point, which must lie in the chart set with DMPlexSetChart() 3112 - size - The support size for point p 3113 3114 Output Parameter: 3115 3116 Note: 3117 This should be called after DMPlexSetChart(). 3118 3119 Level: beginner 3120 3121 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 3122 @*/ 3123 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3124 { 3125 DM_Plex *mesh = (DM_Plex*) dm->data; 3126 PetscErrorCode ierr; 3127 3128 PetscFunctionBegin; 3129 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3130 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 3131 3132 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 3133 PetscFunctionReturn(0); 3134 } 3135 3136 /*@C 3137 DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3138 3139 Not collective 3140 3141 Input Parameters: 3142 + mesh - The DMPlex 3143 - p - The point, which must lie in the chart set with DMPlexSetChart() 3144 3145 Output Parameter: 3146 . support - An array of points which are on the out-edges for point p 3147 3148 Level: beginner 3149 3150 Fortran Notes: 3151 Since it returns an array, this routine is only available in Fortran 90, and you must 3152 include petsc.h90 in your code. 3153 You must also call DMPlexRestoreSupport() after you finish using the returned array. 3154 DMPlexRestoreSupport() is not needed/available in C. 3155 3156 .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart() 3157 @*/ 3158 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3159 { 3160 DM_Plex *mesh = (DM_Plex*) dm->data; 3161 PetscInt off; 3162 PetscErrorCode ierr; 3163 3164 PetscFunctionBegin; 3165 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3166 PetscValidPointer(support, 3); 3167 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3168 *support = &mesh->supports[off]; 3169 PetscFunctionReturn(0); 3170 } 3171 3172 /*@ 3173 DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 3174 3175 Not collective 3176 3177 Input Parameters: 3178 + mesh - The DMPlex 3179 . p - The point, which must lie in the chart set with DMPlexSetChart() 3180 - support - An array of points which are on the out-edges for point p 3181 3182 Output Parameter: 3183 3184 Note: 3185 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 3186 3187 Level: beginner 3188 3189 .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 3190 @*/ 3191 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3192 { 3193 DM_Plex *mesh = (DM_Plex*) dm->data; 3194 PetscInt pStart, pEnd; 3195 PetscInt dof, off, c; 3196 PetscErrorCode ierr; 3197 3198 PetscFunctionBegin; 3199 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3200 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3201 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3202 if (dof) PetscValidPointer(support, 3); 3203 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3204 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); 3205 for (c = 0; c < dof; ++c) { 3206 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); 3207 mesh->supports[off+c] = support[c]; 3208 } 3209 PetscFunctionReturn(0); 3210 } 3211 3212 /*@ 3213 DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 3214 3215 Not collective 3216 3217 Input Parameters: 3218 + mesh - The DMPlex 3219 . p - The point, which must lie in the chart set with DMPlexSetChart() 3220 . supportPos - The local index in the cone where the point should be put 3221 - supportPoint - The mesh point to insert 3222 3223 Level: beginner 3224 3225 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3226 @*/ 3227 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3228 { 3229 DM_Plex *mesh = (DM_Plex*) dm->data; 3230 PetscInt pStart, pEnd; 3231 PetscInt dof, off; 3232 PetscErrorCode ierr; 3233 3234 PetscFunctionBegin; 3235 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3236 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3237 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3238 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3239 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); 3240 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); 3241 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); 3242 mesh->supports[off+supportPos] = supportPoint; 3243 PetscFunctionReturn(0); 3244 } 3245 3246 /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3247 PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3248 { 3249 switch (ct) { 3250 case DM_POLYTOPE_SEGMENT: 3251 if (o == -1) return -2; 3252 break; 3253 case DM_POLYTOPE_TRIANGLE: 3254 if (o == -3) return -1; 3255 if (o == -2) return -3; 3256 if (o == -1) return -2; 3257 break; 3258 case DM_POLYTOPE_QUADRILATERAL: 3259 if (o == -4) return -2; 3260 if (o == -3) return -1; 3261 if (o == -2) return -4; 3262 if (o == -1) return -3; 3263 break; 3264 default: return o; 3265 } 3266 return o; 3267 } 3268 3269 /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3270 PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3271 { 3272 switch (ct) { 3273 case DM_POLYTOPE_SEGMENT: 3274 if ((o == -2) || (o == 1)) return -1; 3275 if (o == -1) return 0; 3276 break; 3277 case DM_POLYTOPE_TRIANGLE: 3278 if (o == -3) return -2; 3279 if (o == -2) return -1; 3280 if (o == -1) return -3; 3281 break; 3282 case DM_POLYTOPE_QUADRILATERAL: 3283 if (o == -4) return -2; 3284 if (o == -3) return -1; 3285 if (o == -2) return -4; 3286 if (o == -1) return -3; 3287 break; 3288 default: return o; 3289 } 3290 return o; 3291 } 3292 3293 /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3294 PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3295 { 3296 PetscInt pStart, pEnd, p; 3297 PetscErrorCode ierr; 3298 3299 PetscFunctionBegin; 3300 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3301 for (p = pStart; p < pEnd; ++p) { 3302 const PetscInt *cone, *ornt; 3303 PetscInt coneSize, c; 3304 3305 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3306 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 3307 ierr = DMPlexGetConeOrientation(dm, p, &ornt);CHKERRQ(ierr); 3308 for (c = 0; c < coneSize; ++c) { 3309 DMPolytopeType ct; 3310 const PetscInt o = ornt[c]; 3311 3312 ierr = DMPlexGetCellType(dm, cone[c], &ct);CHKERRQ(ierr); 3313 switch (ct) { 3314 case DM_POLYTOPE_SEGMENT: 3315 if ((o == -2) || (o == 1)) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3316 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, 0);CHKERRQ(ierr);} 3317 break; 3318 case DM_POLYTOPE_TRIANGLE: 3319 if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);} 3320 if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3321 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);} 3322 break; 3323 case DM_POLYTOPE_QUADRILATERAL: 3324 if (o == -4) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);} 3325 if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);} 3326 if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -4);CHKERRQ(ierr);} 3327 if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);} 3328 break; 3329 default: break; 3330 } 3331 } 3332 } 3333 PetscFunctionReturn(0); 3334 } 3335 3336 static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3337 { 3338 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3339 PetscInt *closure; 3340 const PetscInt *tmp = NULL, *tmpO = NULL; 3341 PetscInt off = 0, tmpSize, t; 3342 PetscErrorCode ierr; 3343 3344 PetscFunctionBeginHot; 3345 if (ornt) { 3346 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3347 if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3348 } 3349 if (*points) { 3350 closure = *points; 3351 } else { 3352 PetscInt maxConeSize, maxSupportSize; 3353 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3354 ierr = DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure);CHKERRQ(ierr); 3355 } 3356 if (useCone) { 3357 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 3358 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 3359 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 3360 } else { 3361 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 3362 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 3363 } 3364 if (ct == DM_POLYTOPE_UNKNOWN) { 3365 closure[off++] = p; 3366 closure[off++] = 0; 3367 for (t = 0; t < tmpSize; ++t) { 3368 closure[off++] = tmp[t]; 3369 closure[off++] = tmpO ? tmpO[t] : 0; 3370 } 3371 } else { 3372 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);CHKERRQ(ierr); 3373 3374 /* We assume that cells with a valid type have faces with a valid type */ 3375 closure[off++] = p; 3376 closure[off++] = ornt; 3377 for (t = 0; t < tmpSize; ++t) { 3378 DMPolytopeType ft; 3379 3380 ierr = DMPlexGetCellType(dm, tmp[t], &ft);CHKERRQ(ierr); 3381 closure[off++] = tmp[arr[t]]; 3382 closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3383 } 3384 } 3385 if (numPoints) *numPoints = tmpSize+1; 3386 if (points) *points = closure; 3387 PetscFunctionReturn(0); 3388 } 3389 3390 /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */ 3391 static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3392 { 3393 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3394 const PetscInt *cone, *ornt; 3395 PetscInt *pts, *closure = NULL; 3396 DMPolytopeType ft; 3397 PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3398 PetscInt dim, coneSize, c, d, clSize, cl; 3399 PetscErrorCode ierr; 3400 3401 PetscFunctionBeginHot; 3402 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3403 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 3404 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3405 ierr = DMPlexGetConeOrientation(dm, point, &ornt);CHKERRQ(ierr); 3406 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3407 coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim+1)-1)/(maxConeSize-1)) : dim+1; 3408 supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1; 3409 maxSize = PetscMax(coneSeries, supportSeries); 3410 if (*points) {pts = *points;} 3411 else {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts);CHKERRQ(ierr);} 3412 c = 0; 3413 pts[c++] = point; 3414 pts[c++] = o; 3415 ierr = DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft);CHKERRQ(ierr); 3416 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure);CHKERRQ(ierr); 3417 for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 3418 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure);CHKERRQ(ierr); 3419 for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];} 3420 ierr = DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure);CHKERRQ(ierr); 3421 for (d = 2; d < coneSize; ++d) { 3422 ierr = DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft);CHKERRQ(ierr); 3423 pts[c++] = cone[arr[d*2+0]]; 3424 pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]); 3425 } 3426 if (dim >= 3) { 3427 for (d = 2; d < coneSize; ++d) { 3428 const PetscInt fpoint = cone[arr[d*2+0]]; 3429 const PetscInt *fcone, *fornt; 3430 PetscInt fconeSize, fc, i; 3431 3432 ierr = DMPlexGetCellType(dm, fpoint, &ft);CHKERRQ(ierr); 3433 const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d])); 3434 ierr = DMPlexGetConeSize(dm, fpoint, &fconeSize);CHKERRQ(ierr); 3435 ierr = DMPlexGetCone(dm, fpoint, &fcone);CHKERRQ(ierr); 3436 ierr = DMPlexGetConeOrientation(dm, fpoint, &fornt);CHKERRQ(ierr); 3437 for (fc = 0; fc < fconeSize; ++fc) { 3438 const PetscInt cp = fcone[farr[fc*2+0]]; 3439 const PetscInt co = farr[fc*2+1]; 3440 3441 for (i = 0; i < c; i += 2) if (pts[i] == cp) break; 3442 if (i == c) { 3443 ierr = DMPlexGetCellType(dm, cp, &ft);CHKERRQ(ierr); 3444 pts[c++] = cp; 3445 pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]); 3446 } 3447 } 3448 } 3449 } 3450 *numPoints = c/2; 3451 *points = pts; 3452 PetscFunctionReturn(0); 3453 } 3454 3455 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3456 { 3457 DMPolytopeType ct; 3458 PetscInt *closure, *fifo; 3459 PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3460 PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3461 PetscInt depth, maxSize; 3462 PetscErrorCode ierr; 3463 3464 PetscFunctionBeginHot; 3465 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3466 if (depth == 1) { 3467 ierr = DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points);CHKERRQ(ierr); 3468 PetscFunctionReturn(0); 3469 } 3470 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3471 if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN; 3472 if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) { 3473 ierr = DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points);CHKERRQ(ierr); 3474 PetscFunctionReturn(0); 3475 } 3476 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3477 coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth+1)-1)/(maxConeSize-1)) : depth+1; 3478 supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1; 3479 maxSize = PetscMax(coneSeries, supportSeries); 3480 ierr = DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3481 if (*points) {closure = *points;} 3482 else {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure);CHKERRQ(ierr);} 3483 closure[closureSize++] = p; 3484 closure[closureSize++] = ornt; 3485 fifo[fifoSize++] = p; 3486 fifo[fifoSize++] = ornt; 3487 fifo[fifoSize++] = ct; 3488 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3489 while (fifoSize - fifoStart) { 3490 const PetscInt q = fifo[fifoStart++]; 3491 const PetscInt o = fifo[fifoStart++]; 3492 const DMPolytopeType qt = (DMPolytopeType) fifo[fifoStart++]; 3493 const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 3494 const PetscInt *tmp, *tmpO; 3495 PetscInt tmpSize, t; 3496 3497 if (PetscDefined(USE_DEBUG)) { 3498 PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2; 3499 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); 3500 } 3501 if (useCone) { 3502 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 3503 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 3504 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 3505 } else { 3506 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 3507 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 3508 tmpO = NULL; 3509 } 3510 for (t = 0; t < tmpSize; ++t) { 3511 const PetscInt ip = useCone && qarr ? qarr[t*2] : t; 3512 const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0; 3513 const PetscInt cp = tmp[ip]; 3514 ierr = DMPlexGetCellType(dm, cp, &ct);CHKERRQ(ierr); 3515 const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3516 PetscInt c; 3517 3518 /* Check for duplicate */ 3519 for (c = 0; c < closureSize; c += 2) { 3520 if (closure[c] == cp) break; 3521 } 3522 if (c == closureSize) { 3523 closure[closureSize++] = cp; 3524 closure[closureSize++] = co; 3525 fifo[fifoSize++] = cp; 3526 fifo[fifoSize++] = co; 3527 fifo[fifoSize++] = ct; 3528 } 3529 } 3530 } 3531 ierr = DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3532 if (numPoints) *numPoints = closureSize/2; 3533 if (points) *points = closure; 3534 PetscFunctionReturn(0); 3535 } 3536 3537 /*@C 3538 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3539 3540 Not collective 3541 3542 Input Parameters: 3543 + dm - The DMPlex 3544 . p - The mesh point 3545 - useCone - PETSC_TRUE for the closure, otherwise return the star 3546 3547 Input/Output Parameter: 3548 . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 3549 if NULL on input, internal storage will be returned, otherwise the provided array is used 3550 3551 Output Parameter: 3552 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3553 3554 Note: 3555 If using internal storage (points is NULL on input), each call overwrites the last output. 3556 3557 Fortran Notes: 3558 Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3559 3560 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3561 3562 Level: beginner 3563 3564 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3565 @*/ 3566 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3567 { 3568 PetscErrorCode ierr; 3569 3570 PetscFunctionBeginHot; 3571 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3572 if (numPoints) PetscValidIntPointer(numPoints, 4); 3573 if (points) PetscValidPointer(points, 5); 3574 ierr = DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points);CHKERRQ(ierr); 3575 PetscFunctionReturn(0); 3576 } 3577 3578 /*@C 3579 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3580 3581 Not collective 3582 3583 Input Parameters: 3584 + dm - The DMPlex 3585 . p - The mesh point 3586 . useCone - PETSC_TRUE for the closure, otherwise return the star 3587 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3588 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3589 3590 Note: 3591 If not using internal storage (points is not NULL on input), this call is unnecessary 3592 3593 Fortran Notes: 3594 Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3595 3596 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3597 3598 Level: beginner 3599 3600 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3601 @*/ 3602 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3603 { 3604 PetscErrorCode ierr; 3605 3606 PetscFunctionBeginHot; 3607 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3608 if (numPoints) *numPoints = 0; 3609 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr); 3610 PetscFunctionReturn(0); 3611 } 3612 3613 /*@ 3614 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3615 3616 Not collective 3617 3618 Input Parameter: 3619 . mesh - The DMPlex 3620 3621 Output Parameters: 3622 + maxConeSize - The maximum number of in-edges 3623 - maxSupportSize - The maximum number of out-edges 3624 3625 Level: beginner 3626 3627 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 3628 @*/ 3629 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3630 { 3631 DM_Plex *mesh = (DM_Plex*) dm->data; 3632 3633 PetscFunctionBegin; 3634 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3635 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 3636 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 3637 PetscFunctionReturn(0); 3638 } 3639 3640 PetscErrorCode DMSetUp_Plex(DM dm) 3641 { 3642 DM_Plex *mesh = (DM_Plex*) dm->data; 3643 PetscInt size; 3644 PetscErrorCode ierr; 3645 3646 PetscFunctionBegin; 3647 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3648 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 3649 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 3650 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 3651 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 3652 ierr = PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt));CHKERRQ(ierr); 3653 if (mesh->maxSupportSize) { 3654 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3655 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 3656 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 3657 ierr = PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt));CHKERRQ(ierr); 3658 } 3659 PetscFunctionReturn(0); 3660 } 3661 3662 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3663 { 3664 PetscErrorCode ierr; 3665 3666 PetscFunctionBegin; 3667 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 3668 ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 3669 if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3670 if (dm->useNatural && dm->sfMigration) { 3671 PetscSF sfMigrationInv,sfNatural; 3672 PetscSection section, sectionSeq; 3673 3674 (*subdm)->sfMigration = dm->sfMigration; 3675 ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr); 3676 ierr = DMGetLocalSection((*subdm), §ion);CHKERRQ(ierr); 3677 ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3678 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq);CHKERRQ(ierr); 3679 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3680 3681 ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3682 (*subdm)->sfNatural = sfNatural; 3683 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3684 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3685 } 3686 PetscFunctionReturn(0); 3687 } 3688 3689 PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 3690 { 3691 PetscErrorCode ierr; 3692 PetscInt i = 0; 3693 3694 PetscFunctionBegin; 3695 ierr = DMClone(dms[0], superdm);CHKERRQ(ierr); 3696 ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr); 3697 (*superdm)->useNatural = PETSC_FALSE; 3698 for (i = 0; i < len; i++) { 3699 if (dms[i]->useNatural && dms[i]->sfMigration) { 3700 PetscSF sfMigrationInv,sfNatural; 3701 PetscSection section, sectionSeq; 3702 3703 (*superdm)->sfMigration = dms[i]->sfMigration; 3704 ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr); 3705 (*superdm)->useNatural = PETSC_TRUE; 3706 ierr = DMGetLocalSection((*superdm), §ion);CHKERRQ(ierr); 3707 ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3708 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq);CHKERRQ(ierr); 3709 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3710 3711 ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3712 (*superdm)->sfNatural = sfNatural; 3713 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3714 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3715 break; 3716 } 3717 } 3718 PetscFunctionReturn(0); 3719 } 3720 3721 /*@ 3722 DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3723 3724 Not collective 3725 3726 Input Parameter: 3727 . mesh - The DMPlex 3728 3729 Output Parameter: 3730 3731 Note: 3732 This should be called after all calls to DMPlexSetCone() 3733 3734 Level: beginner 3735 3736 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 3737 @*/ 3738 PetscErrorCode DMPlexSymmetrize(DM dm) 3739 { 3740 DM_Plex *mesh = (DM_Plex*) dm->data; 3741 PetscInt *offsets; 3742 PetscInt supportSize; 3743 PetscInt pStart, pEnd, p; 3744 PetscErrorCode ierr; 3745 3746 PetscFunctionBegin; 3747 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3748 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 3749 ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3750 /* Calculate support sizes */ 3751 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3752 for (p = pStart; p < pEnd; ++p) { 3753 PetscInt dof, off, c; 3754 3755 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3756 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3757 for (c = off; c < off+dof; ++c) { 3758 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 3759 } 3760 } 3761 for (p = pStart; p < pEnd; ++p) { 3762 PetscInt dof; 3763 3764 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3765 3766 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 3767 } 3768 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3769 /* Calculate supports */ 3770 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 3771 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 3772 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 3773 for (p = pStart; p < pEnd; ++p) { 3774 PetscInt dof, off, c; 3775 3776 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3777 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3778 for (c = off; c < off+dof; ++c) { 3779 const PetscInt q = mesh->cones[c]; 3780 PetscInt offS; 3781 3782 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 3783 3784 mesh->supports[offS+offsets[q]] = p; 3785 ++offsets[q]; 3786 } 3787 } 3788 ierr = PetscFree(offsets);CHKERRQ(ierr); 3789 ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3790 PetscFunctionReturn(0); 3791 } 3792 3793 static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3794 { 3795 IS stratumIS; 3796 PetscErrorCode ierr; 3797 3798 PetscFunctionBegin; 3799 if (pStart >= pEnd) PetscFunctionReturn(0); 3800 if (PetscDefined(USE_DEBUG)) { 3801 PetscInt qStart, qEnd, numLevels, level; 3802 PetscBool overlap = PETSC_FALSE; 3803 ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr); 3804 for (level = 0; level < numLevels; level++) { 3805 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3806 if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3807 } 3808 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); 3809 } 3810 ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr); 3811 ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr); 3812 ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 3813 PetscFunctionReturn(0); 3814 } 3815 3816 /*@ 3817 DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 3818 can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3819 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3820 the DAG. 3821 3822 Collective on dm 3823 3824 Input Parameter: 3825 . mesh - The DMPlex 3826 3827 Output Parameter: 3828 3829 Notes: 3830 Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3831 meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 3832 until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3833 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3834 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3835 3836 The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3837 if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3838 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 3839 to interpolate only that one (e0), so that 3840 $ cone(c0) = {e0, v2} 3841 $ cone(e0) = {v0, v1} 3842 If DMPlexStratify() is run on this mesh, it will give depths 3843 $ depth 0 = {v0, v1, v2} 3844 $ depth 1 = {e0, c0} 3845 where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3846 3847 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3848 3849 Level: beginner 3850 3851 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes() 3852 @*/ 3853 PetscErrorCode DMPlexStratify(DM dm) 3854 { 3855 DM_Plex *mesh = (DM_Plex*) dm->data; 3856 DMLabel label; 3857 PetscInt pStart, pEnd, p; 3858 PetscInt numRoots = 0, numLeaves = 0; 3859 PetscErrorCode ierr; 3860 3861 PetscFunctionBegin; 3862 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3863 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3864 3865 /* Create depth label */ 3866 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3867 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 3868 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3869 3870 { 3871 /* Initialize roots and count leaves */ 3872 PetscInt sMin = PETSC_MAX_INT; 3873 PetscInt sMax = PETSC_MIN_INT; 3874 PetscInt coneSize, supportSize; 3875 3876 for (p = pStart; p < pEnd; ++p) { 3877 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3878 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3879 if (!coneSize && supportSize) { 3880 sMin = PetscMin(p, sMin); 3881 sMax = PetscMax(p, sMax); 3882 ++numRoots; 3883 } else if (!supportSize && coneSize) { 3884 ++numLeaves; 3885 } else if (!supportSize && !coneSize) { 3886 /* Isolated points */ 3887 sMin = PetscMin(p, sMin); 3888 sMax = PetscMax(p, sMax); 3889 } 3890 } 3891 ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr); 3892 } 3893 3894 if (numRoots + numLeaves == (pEnd - pStart)) { 3895 PetscInt sMin = PETSC_MAX_INT; 3896 PetscInt sMax = PETSC_MIN_INT; 3897 PetscInt coneSize, supportSize; 3898 3899 for (p = pStart; p < pEnd; ++p) { 3900 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3901 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3902 if (!supportSize && coneSize) { 3903 sMin = PetscMin(p, sMin); 3904 sMax = PetscMax(p, sMax); 3905 } 3906 } 3907 ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr); 3908 } else { 3909 PetscInt level = 0; 3910 PetscInt qStart, qEnd, q; 3911 3912 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3913 while (qEnd > qStart) { 3914 PetscInt sMin = PETSC_MAX_INT; 3915 PetscInt sMax = PETSC_MIN_INT; 3916 3917 for (q = qStart; q < qEnd; ++q) { 3918 const PetscInt *support; 3919 PetscInt supportSize, s; 3920 3921 ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr); 3922 ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr); 3923 for (s = 0; s < supportSize; ++s) { 3924 sMin = PetscMin(support[s], sMin); 3925 sMax = PetscMax(support[s], sMax); 3926 } 3927 } 3928 ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr); 3929 ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr); 3930 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3931 } 3932 } 3933 { /* just in case there is an empty process */ 3934 PetscInt numValues, maxValues = 0, v; 3935 3936 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 3937 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 3938 for (v = numValues; v < maxValues; v++) { 3939 ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr); 3940 } 3941 } 3942 ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr); 3943 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3944 PetscFunctionReturn(0); 3945 } 3946 3947 PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 3948 { 3949 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3950 PetscInt dim, depth, pheight, coneSize; 3951 PetscErrorCode ierr; 3952 3953 PetscFunctionBeginHot; 3954 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3955 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3956 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3957 pheight = depth - pdepth; 3958 if (depth <= 1) { 3959 switch (pdepth) { 3960 case 0: ct = DM_POLYTOPE_POINT;break; 3961 case 1: 3962 switch (coneSize) { 3963 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3964 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3965 case 4: 3966 switch (dim) { 3967 case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 3968 case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 3969 default: break; 3970 } 3971 break; 3972 case 5: ct = DM_POLYTOPE_PYRAMID;break; 3973 case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3974 case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 3975 default: break; 3976 } 3977 } 3978 } else { 3979 if (pdepth == 0) { 3980 ct = DM_POLYTOPE_POINT; 3981 } else if (pheight == 0) { 3982 switch (dim) { 3983 case 1: 3984 switch (coneSize) { 3985 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3986 default: break; 3987 } 3988 break; 3989 case 2: 3990 switch (coneSize) { 3991 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3992 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3993 default: break; 3994 } 3995 break; 3996 case 3: 3997 switch (coneSize) { 3998 case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 3999 case 5: 4000 { 4001 const PetscInt *cone; 4002 PetscInt faceConeSize; 4003 4004 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 4005 ierr = DMPlexGetConeSize(dm, cone[0], &faceConeSize);CHKERRQ(ierr); 4006 switch (faceConeSize) { 4007 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 4008 case 4: ct = DM_POLYTOPE_PYRAMID;break; 4009 } 4010 } 4011 break; 4012 case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 4013 default: break; 4014 } 4015 break; 4016 default: break; 4017 } 4018 } else if (pheight > 0) { 4019 switch (coneSize) { 4020 case 2: ct = DM_POLYTOPE_SEGMENT;break; 4021 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 4022 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 4023 default: break; 4024 } 4025 } 4026 } 4027 *pt = ct; 4028 PetscFunctionReturn(0); 4029 } 4030 4031 /*@ 4032 DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4033 4034 Collective on dm 4035 4036 Input Parameter: 4037 . mesh - The DMPlex 4038 4039 DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 4040 4041 Level: developer 4042 4043 Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 4044 internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 4045 automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 4046 4047 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel() 4048 @*/ 4049 PetscErrorCode DMPlexComputeCellTypes(DM dm) 4050 { 4051 DM_Plex *mesh; 4052 DMLabel ctLabel; 4053 PetscInt pStart, pEnd, p; 4054 PetscErrorCode ierr; 4055 4056 PetscFunctionBegin; 4057 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4058 mesh = (DM_Plex *) dm->data; 4059 ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr); 4060 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 4061 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4062 for (p = pStart; p < pEnd; ++p) { 4063 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4064 PetscInt pdepth; 4065 4066 ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr); 4067 ierr = DMPlexComputeCellType_Internal(dm, p, pdepth, &ct);CHKERRQ(ierr); 4068 if (ct == DM_POLYTOPE_UNKNOWN) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p); 4069 ierr = DMLabelSetValue(ctLabel, p, ct);CHKERRQ(ierr); 4070 } 4071 ierr = PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState);CHKERRQ(ierr); 4072 ierr = PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr); 4073 PetscFunctionReturn(0); 4074 } 4075 4076 /*@C 4077 DMPlexGetJoin - Get an array for the join of the set of points 4078 4079 Not Collective 4080 4081 Input Parameters: 4082 + dm - The DMPlex object 4083 . numPoints - The number of input points for the join 4084 - points - The input points 4085 4086 Output Parameters: 4087 + numCoveredPoints - The number of points in the join 4088 - coveredPoints - The points in the join 4089 4090 Level: intermediate 4091 4092 Note: Currently, this is restricted to a single level join 4093 4094 Fortran Notes: 4095 Since it returns an array, this routine is only available in Fortran 90, and you must 4096 include petsc.h90 in your code. 4097 4098 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4099 4100 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 4101 @*/ 4102 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4103 { 4104 DM_Plex *mesh = (DM_Plex*) dm->data; 4105 PetscInt *join[2]; 4106 PetscInt joinSize, i = 0; 4107 PetscInt dof, off, p, c, m; 4108 PetscErrorCode ierr; 4109 4110 PetscFunctionBegin; 4111 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4112 PetscValidIntPointer(points, 3); 4113 PetscValidIntPointer(numCoveredPoints, 4); 4114 PetscValidPointer(coveredPoints, 5); 4115 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4116 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4117 /* Copy in support of first point */ 4118 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 4119 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 4120 for (joinSize = 0; joinSize < dof; ++joinSize) { 4121 join[i][joinSize] = mesh->supports[off+joinSize]; 4122 } 4123 /* Check each successive support */ 4124 for (p = 1; p < numPoints; ++p) { 4125 PetscInt newJoinSize = 0; 4126 4127 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 4128 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 4129 for (c = 0; c < dof; ++c) { 4130 const PetscInt point = mesh->supports[off+c]; 4131 4132 for (m = 0; m < joinSize; ++m) { 4133 if (point == join[i][m]) { 4134 join[1-i][newJoinSize++] = point; 4135 break; 4136 } 4137 } 4138 } 4139 joinSize = newJoinSize; 4140 i = 1-i; 4141 } 4142 *numCoveredPoints = joinSize; 4143 *coveredPoints = join[i]; 4144 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4145 PetscFunctionReturn(0); 4146 } 4147 4148 /*@C 4149 DMPlexRestoreJoin - Restore an array for the join of the set of points 4150 4151 Not Collective 4152 4153 Input Parameters: 4154 + dm - The DMPlex object 4155 . numPoints - The number of input points for the join 4156 - points - The input points 4157 4158 Output Parameters: 4159 + numCoveredPoints - The number of points in the join 4160 - coveredPoints - The points in the join 4161 4162 Fortran Notes: 4163 Since it returns an array, this routine is only available in Fortran 90, and you must 4164 include petsc.h90 in your code. 4165 4166 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4167 4168 Level: intermediate 4169 4170 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 4171 @*/ 4172 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4173 { 4174 PetscErrorCode ierr; 4175 4176 PetscFunctionBegin; 4177 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4178 if (points) PetscValidIntPointer(points,3); 4179 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4180 PetscValidPointer(coveredPoints, 5); 4181 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4182 if (numCoveredPoints) *numCoveredPoints = 0; 4183 PetscFunctionReturn(0); 4184 } 4185 4186 /*@C 4187 DMPlexGetFullJoin - Get an array for the join of the set of points 4188 4189 Not Collective 4190 4191 Input Parameters: 4192 + dm - The DMPlex object 4193 . numPoints - The number of input points for the join 4194 - points - The input points 4195 4196 Output Parameters: 4197 + numCoveredPoints - The number of points in the join 4198 - coveredPoints - The points in the join 4199 4200 Fortran Notes: 4201 Since it returns an array, this routine is only available in Fortran 90, and you must 4202 include petsc.h90 in your code. 4203 4204 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4205 4206 Level: intermediate 4207 4208 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 4209 @*/ 4210 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4211 { 4212 DM_Plex *mesh = (DM_Plex*) dm->data; 4213 PetscInt *offsets, **closures; 4214 PetscInt *join[2]; 4215 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 4216 PetscInt p, d, c, m, ms; 4217 PetscErrorCode ierr; 4218 4219 PetscFunctionBegin; 4220 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4221 PetscValidIntPointer(points, 3); 4222 PetscValidIntPointer(numCoveredPoints, 4); 4223 PetscValidPointer(coveredPoints, 5); 4224 4225 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4226 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 4227 ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4228 ms = mesh->maxSupportSize; 4229 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 4230 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 4231 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 4232 4233 for (p = 0; p < numPoints; ++p) { 4234 PetscInt closureSize; 4235 4236 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 4237 4238 offsets[p*(depth+2)+0] = 0; 4239 for (d = 0; d < depth+1; ++d) { 4240 PetscInt pStart, pEnd, i; 4241 4242 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 4243 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4244 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4245 offsets[p*(depth+2)+d+1] = i; 4246 break; 4247 } 4248 } 4249 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4250 } 4251 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); 4252 } 4253 for (d = 0; d < depth+1; ++d) { 4254 PetscInt dof; 4255 4256 /* Copy in support of first point */ 4257 dof = offsets[d+1] - offsets[d]; 4258 for (joinSize = 0; joinSize < dof; ++joinSize) { 4259 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4260 } 4261 /* Check each successive cone */ 4262 for (p = 1; p < numPoints && joinSize; ++p) { 4263 PetscInt newJoinSize = 0; 4264 4265 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4266 for (c = 0; c < dof; ++c) { 4267 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4268 4269 for (m = 0; m < joinSize; ++m) { 4270 if (point == join[i][m]) { 4271 join[1-i][newJoinSize++] = point; 4272 break; 4273 } 4274 } 4275 } 4276 joinSize = newJoinSize; 4277 i = 1-i; 4278 } 4279 if (joinSize) break; 4280 } 4281 *numCoveredPoints = joinSize; 4282 *coveredPoints = join[i]; 4283 for (p = 0; p < numPoints; ++p) { 4284 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 4285 } 4286 ierr = PetscFree(closures);CHKERRQ(ierr); 4287 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4288 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4289 PetscFunctionReturn(0); 4290 } 4291 4292 /*@C 4293 DMPlexGetMeet - Get an array for the meet of the set of points 4294 4295 Not Collective 4296 4297 Input Parameters: 4298 + dm - The DMPlex object 4299 . numPoints - The number of input points for the meet 4300 - points - The input points 4301 4302 Output Parameters: 4303 + numCoveredPoints - The number of points in the meet 4304 - coveredPoints - The points in the meet 4305 4306 Level: intermediate 4307 4308 Note: Currently, this is restricted to a single level meet 4309 4310 Fortran Notes: 4311 Since it returns an array, this routine is only available in Fortran 90, and you must 4312 include petsc.h90 in your code. 4313 4314 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4315 4316 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 4317 @*/ 4318 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4319 { 4320 DM_Plex *mesh = (DM_Plex*) dm->data; 4321 PetscInt *meet[2]; 4322 PetscInt meetSize, i = 0; 4323 PetscInt dof, off, p, c, m; 4324 PetscErrorCode ierr; 4325 4326 PetscFunctionBegin; 4327 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4328 PetscValidPointer(points, 3); 4329 PetscValidPointer(numCoveringPoints, 4); 4330 PetscValidPointer(coveringPoints, 5); 4331 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4332 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4333 /* Copy in cone of first point */ 4334 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 4335 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 4336 for (meetSize = 0; meetSize < dof; ++meetSize) { 4337 meet[i][meetSize] = mesh->cones[off+meetSize]; 4338 } 4339 /* Check each successive cone */ 4340 for (p = 1; p < numPoints; ++p) { 4341 PetscInt newMeetSize = 0; 4342 4343 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 4344 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 4345 for (c = 0; c < dof; ++c) { 4346 const PetscInt point = mesh->cones[off+c]; 4347 4348 for (m = 0; m < meetSize; ++m) { 4349 if (point == meet[i][m]) { 4350 meet[1-i][newMeetSize++] = point; 4351 break; 4352 } 4353 } 4354 } 4355 meetSize = newMeetSize; 4356 i = 1-i; 4357 } 4358 *numCoveringPoints = meetSize; 4359 *coveringPoints = meet[i]; 4360 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4361 PetscFunctionReturn(0); 4362 } 4363 4364 /*@C 4365 DMPlexRestoreMeet - Restore an array for the meet of the set of points 4366 4367 Not Collective 4368 4369 Input Parameters: 4370 + dm - The DMPlex object 4371 . numPoints - The number of input points for the meet 4372 - points - The input points 4373 4374 Output Parameters: 4375 + numCoveredPoints - The number of points in the meet 4376 - coveredPoints - The points in the meet 4377 4378 Level: intermediate 4379 4380 Fortran Notes: 4381 Since it returns an array, this routine is only available in Fortran 90, and you must 4382 include petsc.h90 in your code. 4383 4384 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4385 4386 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 4387 @*/ 4388 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4389 { 4390 PetscErrorCode ierr; 4391 4392 PetscFunctionBegin; 4393 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4394 if (points) PetscValidIntPointer(points,3); 4395 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4396 PetscValidPointer(coveredPoints,5); 4397 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4398 if (numCoveredPoints) *numCoveredPoints = 0; 4399 PetscFunctionReturn(0); 4400 } 4401 4402 /*@C 4403 DMPlexGetFullMeet - Get an array for the meet of the set of points 4404 4405 Not Collective 4406 4407 Input Parameters: 4408 + dm - The DMPlex object 4409 . numPoints - The number of input points for the meet 4410 - points - The input points 4411 4412 Output Parameters: 4413 + numCoveredPoints - The number of points in the meet 4414 - coveredPoints - The points in the meet 4415 4416 Level: intermediate 4417 4418 Fortran Notes: 4419 Since it returns an array, this routine is only available in Fortran 90, and you must 4420 include petsc.h90 in your code. 4421 4422 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4423 4424 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 4425 @*/ 4426 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4427 { 4428 DM_Plex *mesh = (DM_Plex*) dm->data; 4429 PetscInt *offsets, **closures; 4430 PetscInt *meet[2]; 4431 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 4432 PetscInt p, h, c, m, mc; 4433 PetscErrorCode ierr; 4434 4435 PetscFunctionBegin; 4436 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4437 PetscValidPointer(points, 3); 4438 PetscValidPointer(numCoveredPoints, 4); 4439 PetscValidPointer(coveredPoints, 5); 4440 4441 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 4442 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 4443 ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4444 mc = mesh->maxConeSize; 4445 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 4446 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4447 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4448 4449 for (p = 0; p < numPoints; ++p) { 4450 PetscInt closureSize; 4451 4452 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 4453 4454 offsets[p*(height+2)+0] = 0; 4455 for (h = 0; h < height+1; ++h) { 4456 PetscInt pStart, pEnd, i; 4457 4458 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 4459 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4460 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4461 offsets[p*(height+2)+h+1] = i; 4462 break; 4463 } 4464 } 4465 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4466 } 4467 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); 4468 } 4469 for (h = 0; h < height+1; ++h) { 4470 PetscInt dof; 4471 4472 /* Copy in cone of first point */ 4473 dof = offsets[h+1] - offsets[h]; 4474 for (meetSize = 0; meetSize < dof; ++meetSize) { 4475 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4476 } 4477 /* Check each successive cone */ 4478 for (p = 1; p < numPoints && meetSize; ++p) { 4479 PetscInt newMeetSize = 0; 4480 4481 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4482 for (c = 0; c < dof; ++c) { 4483 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4484 4485 for (m = 0; m < meetSize; ++m) { 4486 if (point == meet[i][m]) { 4487 meet[1-i][newMeetSize++] = point; 4488 break; 4489 } 4490 } 4491 } 4492 meetSize = newMeetSize; 4493 i = 1-i; 4494 } 4495 if (meetSize) break; 4496 } 4497 *numCoveredPoints = meetSize; 4498 *coveredPoints = meet[i]; 4499 for (p = 0; p < numPoints; ++p) { 4500 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 4501 } 4502 ierr = PetscFree(closures);CHKERRQ(ierr); 4503 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4504 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4505 PetscFunctionReturn(0); 4506 } 4507 4508 /*@C 4509 DMPlexEqual - Determine if two DMs have the same topology 4510 4511 Not Collective 4512 4513 Input Parameters: 4514 + dmA - A DMPlex object 4515 - dmB - A DMPlex object 4516 4517 Output Parameters: 4518 . equal - PETSC_TRUE if the topologies are identical 4519 4520 Level: intermediate 4521 4522 Notes: 4523 We are not solving graph isomorphism, so we do not permutation. 4524 4525 .seealso: DMPlexGetCone() 4526 @*/ 4527 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 4528 { 4529 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 4530 PetscErrorCode ierr; 4531 4532 PetscFunctionBegin; 4533 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 4534 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4535 PetscValidPointer(equal, 3); 4536 4537 *equal = PETSC_FALSE; 4538 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 4539 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 4540 if (depth != depthB) PetscFunctionReturn(0); 4541 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 4542 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 4543 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 4544 for (p = pStart; p < pEnd; ++p) { 4545 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 4546 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 4547 4548 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 4549 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 4550 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 4551 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 4552 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 4553 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 4554 if (coneSize != coneSizeB) PetscFunctionReturn(0); 4555 for (c = 0; c < coneSize; ++c) { 4556 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 4557 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 4558 } 4559 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 4560 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 4561 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 4562 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 4563 if (supportSize != supportSizeB) PetscFunctionReturn(0); 4564 for (s = 0; s < supportSize; ++s) { 4565 if (support[s] != supportB[s]) PetscFunctionReturn(0); 4566 } 4567 } 4568 *equal = PETSC_TRUE; 4569 PetscFunctionReturn(0); 4570 } 4571 4572 /*@C 4573 DMPlexGetNumFaceVertices - Returns the number of vertices on a face 4574 4575 Not Collective 4576 4577 Input Parameters: 4578 + dm - The DMPlex 4579 . cellDim - The cell dimension 4580 - numCorners - The number of vertices on a cell 4581 4582 Output Parameters: 4583 . numFaceVertices - The number of vertices on a face 4584 4585 Level: developer 4586 4587 Notes: 4588 Of course this can only work for a restricted set of symmetric shapes 4589 4590 .seealso: DMPlexGetCone() 4591 @*/ 4592 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4593 { 4594 MPI_Comm comm; 4595 PetscErrorCode ierr; 4596 4597 PetscFunctionBegin; 4598 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4599 PetscValidPointer(numFaceVertices,4); 4600 switch (cellDim) { 4601 case 0: 4602 *numFaceVertices = 0; 4603 break; 4604 case 1: 4605 *numFaceVertices = 1; 4606 break; 4607 case 2: 4608 switch (numCorners) { 4609 case 3: /* triangle */ 4610 *numFaceVertices = 2; /* Edge has 2 vertices */ 4611 break; 4612 case 4: /* quadrilateral */ 4613 *numFaceVertices = 2; /* Edge has 2 vertices */ 4614 break; 4615 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 4616 *numFaceVertices = 3; /* Edge has 3 vertices */ 4617 break; 4618 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 4619 *numFaceVertices = 3; /* Edge has 3 vertices */ 4620 break; 4621 default: 4622 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4623 } 4624 break; 4625 case 3: 4626 switch (numCorners) { 4627 case 4: /* tetradehdron */ 4628 *numFaceVertices = 3; /* Face has 3 vertices */ 4629 break; 4630 case 6: /* tet cohesive cells */ 4631 *numFaceVertices = 4; /* Face has 4 vertices */ 4632 break; 4633 case 8: /* hexahedron */ 4634 *numFaceVertices = 4; /* Face has 4 vertices */ 4635 break; 4636 case 9: /* tet cohesive Lagrange cells */ 4637 *numFaceVertices = 6; /* Face has 6 vertices */ 4638 break; 4639 case 10: /* quadratic tetrahedron */ 4640 *numFaceVertices = 6; /* Face has 6 vertices */ 4641 break; 4642 case 12: /* hex cohesive Lagrange cells */ 4643 *numFaceVertices = 6; /* Face has 6 vertices */ 4644 break; 4645 case 18: /* quadratic tet cohesive Lagrange cells */ 4646 *numFaceVertices = 6; /* Face has 6 vertices */ 4647 break; 4648 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 4649 *numFaceVertices = 9; /* Face has 9 vertices */ 4650 break; 4651 default: 4652 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4653 } 4654 break; 4655 default: 4656 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 4657 } 4658 PetscFunctionReturn(0); 4659 } 4660 4661 /*@ 4662 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4663 4664 Not Collective 4665 4666 Input Parameter: 4667 . dm - The DMPlex object 4668 4669 Output Parameter: 4670 . depthLabel - The DMLabel recording point depth 4671 4672 Level: developer 4673 4674 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), 4675 @*/ 4676 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4677 { 4678 PetscFunctionBegin; 4679 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4680 PetscValidPointer(depthLabel, 2); 4681 *depthLabel = dm->depthLabel; 4682 PetscFunctionReturn(0); 4683 } 4684 4685 /*@ 4686 DMPlexGetDepth - Get the depth of the DAG representing this mesh 4687 4688 Not Collective 4689 4690 Input Parameter: 4691 . dm - The DMPlex object 4692 4693 Output Parameter: 4694 . depth - The number of strata (breadth first levels) in the DAG 4695 4696 Level: developer 4697 4698 Notes: 4699 This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4700 The point depth is described more in detail in DMPlexGetDepthStratum(). 4701 An empty mesh gives -1. 4702 4703 .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize() 4704 @*/ 4705 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4706 { 4707 DMLabel label; 4708 PetscInt d = 0; 4709 PetscErrorCode ierr; 4710 4711 PetscFunctionBegin; 4712 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4713 PetscValidPointer(depth, 2); 4714 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4715 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 4716 *depth = d-1; 4717 PetscFunctionReturn(0); 4718 } 4719 4720 /*@ 4721 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4722 4723 Not Collective 4724 4725 Input Parameters: 4726 + dm - The DMPlex object 4727 - stratumValue - The requested depth 4728 4729 Output Parameters: 4730 + start - The first point at this depth 4731 - end - One beyond the last point at this depth 4732 4733 Notes: 4734 Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4735 often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4736 higher dimension, e.g., "edges". 4737 4738 Level: developer 4739 4740 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate() 4741 @*/ 4742 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4743 { 4744 DMLabel label; 4745 PetscInt pStart, pEnd; 4746 PetscErrorCode ierr; 4747 4748 PetscFunctionBegin; 4749 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4750 if (start) {PetscValidPointer(start, 3); *start = 0;} 4751 if (end) {PetscValidPointer(end, 4); *end = 0;} 4752 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4753 if (pStart == pEnd) PetscFunctionReturn(0); 4754 if (stratumValue < 0) { 4755 if (start) *start = pStart; 4756 if (end) *end = pEnd; 4757 PetscFunctionReturn(0); 4758 } 4759 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4760 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4761 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 4762 PetscFunctionReturn(0); 4763 } 4764 4765 /*@ 4766 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4767 4768 Not Collective 4769 4770 Input Parameters: 4771 + dm - The DMPlex object 4772 - stratumValue - The requested height 4773 4774 Output Parameters: 4775 + start - The first point at this height 4776 - end - One beyond the last point at this height 4777 4778 Notes: 4779 Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4780 points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4781 stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4782 4783 Level: developer 4784 4785 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight() 4786 @*/ 4787 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4788 { 4789 DMLabel label; 4790 PetscInt depth, pStart, pEnd; 4791 PetscErrorCode ierr; 4792 4793 PetscFunctionBegin; 4794 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4795 if (start) {PetscValidPointer(start, 3); *start = 0;} 4796 if (end) {PetscValidPointer(end, 4); *end = 0;} 4797 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4798 if (pStart == pEnd) PetscFunctionReturn(0); 4799 if (stratumValue < 0) { 4800 if (start) *start = pStart; 4801 if (end) *end = pEnd; 4802 PetscFunctionReturn(0); 4803 } 4804 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4805 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4806 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 4807 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 4808 PetscFunctionReturn(0); 4809 } 4810 4811 /*@ 4812 DMPlexGetPointDepth - Get the depth of a given point 4813 4814 Not Collective 4815 4816 Input Parameters: 4817 + dm - The DMPlex object 4818 - point - The point 4819 4820 Output Parameter: 4821 . depth - The depth of the point 4822 4823 Level: intermediate 4824 4825 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight() 4826 @*/ 4827 PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4828 { 4829 PetscErrorCode ierr; 4830 4831 PetscFunctionBegin; 4832 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4833 PetscValidIntPointer(depth, 3); 4834 ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr); 4835 PetscFunctionReturn(0); 4836 } 4837 4838 /*@ 4839 DMPlexGetPointHeight - Get the height of a given point 4840 4841 Not Collective 4842 4843 Input Parameters: 4844 + dm - The DMPlex object 4845 - point - The point 4846 4847 Output Parameter: 4848 . height - The height of the point 4849 4850 Level: intermediate 4851 4852 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth() 4853 @*/ 4854 PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 4855 { 4856 PetscInt n, pDepth; 4857 PetscErrorCode ierr; 4858 4859 PetscFunctionBegin; 4860 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4861 PetscValidIntPointer(height, 3); 4862 ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr); 4863 ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr); 4864 *height = n - 1 - pDepth; /* DAG depth is n-1 */ 4865 PetscFunctionReturn(0); 4866 } 4867 4868 /*@ 4869 DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4870 4871 Not Collective 4872 4873 Input Parameter: 4874 . dm - The DMPlex object 4875 4876 Output Parameter: 4877 . celltypeLabel - The DMLabel recording cell polytope type 4878 4879 Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4880 DMCreateLabel(dm, "celltype") beforehand. 4881 4882 Level: developer 4883 4884 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel() 4885 @*/ 4886 PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4887 { 4888 PetscErrorCode ierr; 4889 4890 PetscFunctionBegin; 4891 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4892 PetscValidPointer(celltypeLabel, 2); 4893 if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);} 4894 *celltypeLabel = dm->celltypeLabel; 4895 PetscFunctionReturn(0); 4896 } 4897 4898 /*@ 4899 DMPlexGetCellType - Get the polytope type of a given cell 4900 4901 Not Collective 4902 4903 Input Parameters: 4904 + dm - The DMPlex object 4905 - cell - The cell 4906 4907 Output Parameter: 4908 . celltype - The polytope type of the cell 4909 4910 Level: intermediate 4911 4912 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth() 4913 @*/ 4914 PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4915 { 4916 DMLabel label; 4917 PetscInt ct; 4918 PetscErrorCode ierr; 4919 4920 PetscFunctionBegin; 4921 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4922 PetscValidPointer(celltype, 3); 4923 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4924 ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr); 4925 if (ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell); 4926 *celltype = (DMPolytopeType) ct; 4927 PetscFunctionReturn(0); 4928 } 4929 4930 /*@ 4931 DMPlexSetCellType - Set the polytope type of a given cell 4932 4933 Not Collective 4934 4935 Input Parameters: 4936 + dm - The DMPlex object 4937 . cell - The cell 4938 - celltype - The polytope type of the cell 4939 4940 Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 4941 is executed. This function will override the computed type. However, if automatic classification will not succeed 4942 and a user wants to manually specify all types, the classification must be disabled by calling 4943 DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 4944 4945 Level: advanced 4946 4947 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel() 4948 @*/ 4949 PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 4950 { 4951 DMLabel label; 4952 PetscErrorCode ierr; 4953 4954 PetscFunctionBegin; 4955 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4956 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4957 ierr = DMLabelSetValue(label, cell, celltype);CHKERRQ(ierr); 4958 PetscFunctionReturn(0); 4959 } 4960 4961 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 4962 { 4963 PetscSection section, s; 4964 Mat m; 4965 PetscInt maxHeight; 4966 PetscErrorCode ierr; 4967 4968 PetscFunctionBegin; 4969 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 4970 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 4971 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 4972 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 4973 ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr); 4974 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 4975 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 4976 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 4977 ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr); 4978 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 4979 ierr = MatDestroy(&m);CHKERRQ(ierr); 4980 4981 ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr); 4982 ierr = DMCreateDS(*cdm);CHKERRQ(ierr); 4983 PetscFunctionReturn(0); 4984 } 4985 4986 PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 4987 { 4988 Vec coordsLocal; 4989 DM coordsDM; 4990 PetscErrorCode ierr; 4991 4992 PetscFunctionBegin; 4993 *field = NULL; 4994 ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr); 4995 ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr); 4996 if (coordsLocal && coordsDM) { 4997 ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr); 4998 } 4999 PetscFunctionReturn(0); 5000 } 5001 5002 /*@C 5003 DMPlexGetConeSection - Return a section which describes the layout of cone data 5004 5005 Not Collective 5006 5007 Input Parameters: 5008 . dm - The DMPlex object 5009 5010 Output Parameter: 5011 . section - The PetscSection object 5012 5013 Level: developer 5014 5015 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 5016 @*/ 5017 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5018 { 5019 DM_Plex *mesh = (DM_Plex*) dm->data; 5020 5021 PetscFunctionBegin; 5022 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5023 if (section) *section = mesh->coneSection; 5024 PetscFunctionReturn(0); 5025 } 5026 5027 /*@C 5028 DMPlexGetSupportSection - Return a section which describes the layout of support data 5029 5030 Not Collective 5031 5032 Input Parameters: 5033 . dm - The DMPlex object 5034 5035 Output Parameter: 5036 . section - The PetscSection object 5037 5038 Level: developer 5039 5040 .seealso: DMPlexGetConeSection() 5041 @*/ 5042 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5043 { 5044 DM_Plex *mesh = (DM_Plex*) dm->data; 5045 5046 PetscFunctionBegin; 5047 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5048 if (section) *section = mesh->supportSection; 5049 PetscFunctionReturn(0); 5050 } 5051 5052 /*@C 5053 DMPlexGetCones - Return cone data 5054 5055 Not Collective 5056 5057 Input Parameters: 5058 . dm - The DMPlex object 5059 5060 Output Parameter: 5061 . cones - The cone for each point 5062 5063 Level: developer 5064 5065 .seealso: DMPlexGetConeSection() 5066 @*/ 5067 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5068 { 5069 DM_Plex *mesh = (DM_Plex*) dm->data; 5070 5071 PetscFunctionBegin; 5072 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5073 if (cones) *cones = mesh->cones; 5074 PetscFunctionReturn(0); 5075 } 5076 5077 /*@C 5078 DMPlexGetConeOrientations - Return cone orientation data 5079 5080 Not Collective 5081 5082 Input Parameters: 5083 . dm - The DMPlex object 5084 5085 Output Parameter: 5086 . coneOrientations - The array of cone orientations for all points 5087 5088 Level: developer 5089 5090 Notes: 5091 The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation(). 5092 5093 The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation(). 5094 5095 .seealso: DMPlexGetConeSection(), DMPlexGetConeOrientation() 5096 @*/ 5097 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5098 { 5099 DM_Plex *mesh = (DM_Plex*) dm->data; 5100 5101 PetscFunctionBegin; 5102 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5103 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 5104 PetscFunctionReturn(0); 5105 } 5106 5107 /******************************** FEM Support **********************************/ 5108 5109 /* 5110 Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 5111 representing a line in the section. 5112 */ 5113 static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 5114 { 5115 PetscErrorCode ierr; 5116 5117 PetscFunctionBeginHot; 5118 ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr); 5119 if (line < 0) { 5120 *k = 0; 5121 *Nc = 0; 5122 } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 5123 *k = 1; 5124 } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 5125 /* An order k SEM disc has k-1 dofs on an edge */ 5126 ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr); 5127 *k = *k / *Nc + 1; 5128 } 5129 PetscFunctionReturn(0); 5130 } 5131 5132 /*@ 5133 5134 DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5135 lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 5136 section provided (or the section of the DM). 5137 5138 Input Parameters: 5139 + dm - The DM 5140 . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 5141 - section - The PetscSection to reorder, or NULL for the default section 5142 5143 Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5144 degree of the basis. 5145 5146 Example: 5147 A typical interpolated single-quad mesh might order points as 5148 .vb 5149 [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5150 5151 v4 -- e6 -- v3 5152 | | 5153 e7 c0 e8 5154 | | 5155 v1 -- e5 -- v2 5156 .ve 5157 5158 (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5159 dofs in the order of points, e.g., 5160 .vb 5161 c0 -> [0,1,2,3] 5162 v1 -> [4] 5163 ... 5164 e5 -> [8, 9] 5165 .ve 5166 5167 which corresponds to the dofs 5168 .vb 5169 6 10 11 7 5170 13 2 3 15 5171 12 0 1 14 5172 4 8 9 5 5173 .ve 5174 5175 The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5176 .vb 5177 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5178 .ve 5179 5180 After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5181 .vb 5182 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5183 .ve 5184 5185 Level: developer 5186 5187 .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection() 5188 @*/ 5189 PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5190 { 5191 DMLabel label; 5192 PetscInt dim, depth = -1, eStart = -1, Nf; 5193 PetscBool vertexchart; 5194 PetscErrorCode ierr; 5195 5196 PetscFunctionBegin; 5197 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5198 if (dim < 1) PetscFunctionReturn(0); 5199 if (point < 0) { 5200 PetscInt sStart,sEnd; 5201 5202 ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr); 5203 point = sEnd-sStart ? sStart : point; 5204 } 5205 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 5206 if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); } 5207 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5208 if (depth == 1) {eStart = point;} 5209 else if (depth == dim) { 5210 const PetscInt *cone; 5211 5212 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5213 if (dim == 2) eStart = cone[0]; 5214 else if (dim == 3) { 5215 const PetscInt *cone2; 5216 ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 5217 eStart = cone2[0]; 5218 } 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); 5219 } 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); 5220 { /* Determine whether the chart covers all points or just vertices. */ 5221 PetscInt pStart,pEnd,cStart,cEnd; 5222 ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr); 5223 ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr); 5224 if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Just vertices */ 5225 else vertexchart = PETSC_FALSE; /* Assume all interpolated points are in chart */ 5226 } 5227 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5228 for (PetscInt d=1; d<=dim; d++) { 5229 PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5230 PetscInt *perm; 5231 5232 for (f = 0; f < Nf; ++f) { 5233 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5234 size += PetscPowInt(k+1, d)*Nc; 5235 } 5236 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 5237 for (f = 0; f < Nf; ++f) { 5238 switch (d) { 5239 case 1: 5240 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5241 /* 5242 Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5243 We want [ vtx0; edge of length k-1; vtx1 ] 5244 */ 5245 for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5246 for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5247 for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5248 foffset = offset; 5249 break; 5250 case 2: 5251 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 5252 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5253 /* The SEM order is 5254 5255 v_lb, {e_b}, v_rb, 5256 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 5257 v_lt, reverse {e_t}, v_rt 5258 */ 5259 { 5260 const PetscInt of = 0; 5261 const PetscInt oeb = of + PetscSqr(k-1); 5262 const PetscInt oer = oeb + (k-1); 5263 const PetscInt oet = oer + (k-1); 5264 const PetscInt oel = oet + (k-1); 5265 const PetscInt ovlb = oel + (k-1); 5266 const PetscInt ovrb = ovlb + 1; 5267 const PetscInt ovrt = ovrb + 1; 5268 const PetscInt ovlt = ovrt + 1; 5269 PetscInt o; 5270 5271 /* bottom */ 5272 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 5273 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5274 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 5275 /* middle */ 5276 for (i = 0; i < k-1; ++i) { 5277 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 5278 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; 5279 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 5280 } 5281 /* top */ 5282 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 5283 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5284 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 5285 foffset = offset; 5286 } 5287 break; 5288 case 3: 5289 /* The original hex closure is 5290 5291 {c, 5292 f_b, f_t, f_f, f_b, f_r, f_l, 5293 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 5294 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 5295 */ 5296 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5297 /* The SEM order is 5298 Bottom Slice 5299 v_blf, {e^{(k-1)-n}_bf}, v_brf, 5300 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 5301 v_blb, {e_bb}, v_brb, 5302 5303 Middle Slice (j) 5304 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 5305 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 5306 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 5307 5308 Top Slice 5309 v_tlf, {e_tf}, v_trf, 5310 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 5311 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 5312 */ 5313 { 5314 const PetscInt oc = 0; 5315 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 5316 const PetscInt oft = ofb + PetscSqr(k-1); 5317 const PetscInt off = oft + PetscSqr(k-1); 5318 const PetscInt ofk = off + PetscSqr(k-1); 5319 const PetscInt ofr = ofk + PetscSqr(k-1); 5320 const PetscInt ofl = ofr + PetscSqr(k-1); 5321 const PetscInt oebl = ofl + PetscSqr(k-1); 5322 const PetscInt oebb = oebl + (k-1); 5323 const PetscInt oebr = oebb + (k-1); 5324 const PetscInt oebf = oebr + (k-1); 5325 const PetscInt oetf = oebf + (k-1); 5326 const PetscInt oetr = oetf + (k-1); 5327 const PetscInt oetb = oetr + (k-1); 5328 const PetscInt oetl = oetb + (k-1); 5329 const PetscInt oerf = oetl + (k-1); 5330 const PetscInt oelf = oerf + (k-1); 5331 const PetscInt oelb = oelf + (k-1); 5332 const PetscInt oerb = oelb + (k-1); 5333 const PetscInt ovblf = oerb + (k-1); 5334 const PetscInt ovblb = ovblf + 1; 5335 const PetscInt ovbrb = ovblb + 1; 5336 const PetscInt ovbrf = ovbrb + 1; 5337 const PetscInt ovtlf = ovbrf + 1; 5338 const PetscInt ovtrf = ovtlf + 1; 5339 const PetscInt ovtrb = ovtrf + 1; 5340 const PetscInt ovtlb = ovtrb + 1; 5341 PetscInt o, n; 5342 5343 /* Bottom Slice */ 5344 /* bottom */ 5345 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 5346 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5347 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 5348 /* middle */ 5349 for (i = 0; i < k-1; ++i) { 5350 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5351 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;} 5352 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 5353 } 5354 /* top */ 5355 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 5356 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5357 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 5358 5359 /* Middle Slice */ 5360 for (j = 0; j < k-1; ++j) { 5361 /* bottom */ 5362 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 5363 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; 5364 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 5365 /* middle */ 5366 for (i = 0; i < k-1; ++i) { 5367 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 5368 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; 5369 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 5370 } 5371 /* top */ 5372 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 5373 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; 5374 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 5375 } 5376 5377 /* Top Slice */ 5378 /* bottom */ 5379 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 5380 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5381 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 5382 /* middle */ 5383 for (i = 0; i < k-1; ++i) { 5384 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 5385 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 5386 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 5387 } 5388 /* top */ 5389 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 5390 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5391 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 5392 5393 foffset = offset; 5394 } 5395 break; 5396 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d); 5397 } 5398 } 5399 if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 5400 /* Check permutation */ 5401 { 5402 PetscInt *check; 5403 5404 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 5405 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]);} 5406 for (i = 0; i < size; ++i) check[perm[i]] = i; 5407 for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 5408 ierr = PetscFree(check);CHKERRQ(ierr); 5409 } 5410 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 5411 } 5412 PetscFunctionReturn(0); 5413 } 5414 5415 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5416 { 5417 PetscDS prob; 5418 PetscInt depth, Nf, h; 5419 DMLabel label; 5420 PetscErrorCode ierr; 5421 5422 PetscFunctionBeginHot; 5423 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 5424 Nf = prob->Nf; 5425 label = dm->depthLabel; 5426 *dspace = NULL; 5427 if (field < Nf) { 5428 PetscObject disc = prob->disc[field]; 5429 5430 if (disc->classid == PETSCFE_CLASSID) { 5431 PetscDualSpace dsp; 5432 5433 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 5434 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 5435 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 5436 h = depth - 1 - h; 5437 if (h) { 5438 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 5439 } else { 5440 *dspace = dsp; 5441 } 5442 } 5443 } 5444 PetscFunctionReturn(0); 5445 } 5446 5447 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5448 { 5449 PetscScalar *array, *vArray; 5450 const PetscInt *cone, *coneO; 5451 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5452 PetscErrorCode ierr; 5453 5454 PetscFunctionBeginHot; 5455 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5456 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5457 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5458 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5459 if (!values || !*values) { 5460 if ((point >= pStart) && (point < pEnd)) { 5461 PetscInt dof; 5462 5463 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5464 size += dof; 5465 } 5466 for (p = 0; p < numPoints; ++p) { 5467 const PetscInt cp = cone[p]; 5468 PetscInt dof; 5469 5470 if ((cp < pStart) || (cp >= pEnd)) continue; 5471 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5472 size += dof; 5473 } 5474 if (!values) { 5475 if (csize) *csize = size; 5476 PetscFunctionReturn(0); 5477 } 5478 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 5479 } else { 5480 array = *values; 5481 } 5482 size = 0; 5483 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 5484 if ((point >= pStart) && (point < pEnd)) { 5485 PetscInt dof, off, d; 5486 PetscScalar *varr; 5487 5488 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5489 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5490 varr = &vArray[off]; 5491 for (d = 0; d < dof; ++d, ++offset) { 5492 array[offset] = varr[d]; 5493 } 5494 size += dof; 5495 } 5496 for (p = 0; p < numPoints; ++p) { 5497 const PetscInt cp = cone[p]; 5498 PetscInt o = coneO[p]; 5499 PetscInt dof, off, d; 5500 PetscScalar *varr; 5501 5502 if ((cp < pStart) || (cp >= pEnd)) continue; 5503 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5504 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 5505 varr = &vArray[off]; 5506 if (o >= 0) { 5507 for (d = 0; d < dof; ++d, ++offset) { 5508 array[offset] = varr[d]; 5509 } 5510 } else { 5511 for (d = dof-1; d >= 0; --d, ++offset) { 5512 array[offset] = varr[d]; 5513 } 5514 } 5515 size += dof; 5516 } 5517 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 5518 if (!*values) { 5519 if (csize) *csize = size; 5520 *values = array; 5521 } else { 5522 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5523 *csize = size; 5524 } 5525 PetscFunctionReturn(0); 5526 } 5527 5528 /* Compress out points not in the section */ 5529 PETSC_STATIC_INLINE PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 5530 { 5531 const PetscInt np = *numPoints; 5532 PetscInt pStart, pEnd, p, q; 5533 PetscErrorCode ierr; 5534 5535 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5536 for (p = 0, q = 0; p < np; ++p) { 5537 const PetscInt r = points[p*2]; 5538 if ((r >= pStart) && (r < pEnd)) { 5539 points[q*2] = r; 5540 points[q*2+1] = points[p*2+1]; 5541 ++q; 5542 } 5543 } 5544 *numPoints = q; 5545 return 0; 5546 } 5547 5548 /* Compressed closure does not apply closure permutation */ 5549 PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5550 { 5551 const PetscInt *cla = NULL; 5552 PetscInt np, *pts = NULL; 5553 PetscErrorCode ierr; 5554 5555 PetscFunctionBeginHot; 5556 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 5557 if (*clPoints) { 5558 PetscInt dof, off; 5559 5560 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 5561 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 5562 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 5563 np = dof/2; 5564 pts = (PetscInt *) &cla[off]; 5565 } else { 5566 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 5567 ierr = CompressPoints_Private(section, &np, pts);CHKERRQ(ierr); 5568 } 5569 *numPoints = np; 5570 *points = pts; 5571 *clp = cla; 5572 PetscFunctionReturn(0); 5573 } 5574 5575 PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5576 { 5577 PetscErrorCode ierr; 5578 5579 PetscFunctionBeginHot; 5580 if (!*clPoints) { 5581 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 5582 } else { 5583 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 5584 } 5585 *numPoints = 0; 5586 *points = NULL; 5587 *clSec = NULL; 5588 *clPoints = NULL; 5589 *clp = NULL; 5590 PetscFunctionReturn(0); 5591 } 5592 5593 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[]) 5594 { 5595 PetscInt offset = 0, p; 5596 const PetscInt **perms = NULL; 5597 const PetscScalar **flips = NULL; 5598 PetscErrorCode ierr; 5599 5600 PetscFunctionBeginHot; 5601 *size = 0; 5602 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5603 for (p = 0; p < numPoints; p++) { 5604 const PetscInt point = points[2*p]; 5605 const PetscInt *perm = perms ? perms[p] : NULL; 5606 const PetscScalar *flip = flips ? flips[p] : NULL; 5607 PetscInt dof, off, d; 5608 const PetscScalar *varr; 5609 5610 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5611 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5612 varr = &vArray[off]; 5613 if (clperm) { 5614 if (perm) { 5615 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 5616 } else { 5617 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 5618 } 5619 if (flip) { 5620 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 5621 } 5622 } else { 5623 if (perm) { 5624 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 5625 } else { 5626 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 5627 } 5628 if (flip) { 5629 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 5630 } 5631 } 5632 offset += dof; 5633 } 5634 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5635 *size = offset; 5636 PetscFunctionReturn(0); 5637 } 5638 5639 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[]) 5640 { 5641 PetscInt offset = 0, f; 5642 PetscErrorCode ierr; 5643 5644 PetscFunctionBeginHot; 5645 *size = 0; 5646 for (f = 0; f < numFields; ++f) { 5647 PetscInt p; 5648 const PetscInt **perms = NULL; 5649 const PetscScalar **flips = NULL; 5650 5651 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5652 for (p = 0; p < numPoints; p++) { 5653 const PetscInt point = points[2*p]; 5654 PetscInt fdof, foff, b; 5655 const PetscScalar *varr; 5656 const PetscInt *perm = perms ? perms[p] : NULL; 5657 const PetscScalar *flip = flips ? flips[p] : NULL; 5658 5659 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5660 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5661 varr = &vArray[foff]; 5662 if (clperm) { 5663 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 5664 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 5665 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 5666 } else { 5667 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 5668 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 5669 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 5670 } 5671 offset += fdof; 5672 } 5673 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5674 } 5675 *size = offset; 5676 PetscFunctionReturn(0); 5677 } 5678 5679 /*@C 5680 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5681 5682 Not collective 5683 5684 Input Parameters: 5685 + dm - The DM 5686 . section - The section describing the layout in v, or NULL to use the default section 5687 . v - The local vector 5688 - point - The point in the DM 5689 5690 Input/Output Parameters: 5691 + csize - The size of the input values array, or NULL; on output the number of values in the closure 5692 - values - An array to use for the values, or NULL to have it allocated automatically; 5693 if the user provided NULL, it is a borrowed array and should not be freed 5694 5695 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 5696 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 5697 $ assembly function, and a user may already have allocated storage for this operation. 5698 $ 5699 $ A typical use could be 5700 $ 5701 $ values = NULL; 5702 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5703 $ for (cl = 0; cl < clSize; ++cl) { 5704 $ <Compute on closure> 5705 $ } 5706 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5707 $ 5708 $ or 5709 $ 5710 $ PetscMalloc1(clMaxSize, &values); 5711 $ for (p = pStart; p < pEnd; ++p) { 5712 $ clSize = clMaxSize; 5713 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5714 $ for (cl = 0; cl < clSize; ++cl) { 5715 $ <Compute on closure> 5716 $ } 5717 $ } 5718 $ PetscFree(values); 5719 5720 Fortran Notes: 5721 Since it returns an array, this routine is only available in Fortran 90, and you must 5722 include petsc.h90 in your code. 5723 5724 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5725 5726 Level: intermediate 5727 5728 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5729 @*/ 5730 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5731 { 5732 PetscSection clSection; 5733 IS clPoints; 5734 PetscInt *points = NULL; 5735 const PetscInt *clp, *perm; 5736 PetscInt depth, numFields, numPoints, asize; 5737 PetscErrorCode ierr; 5738 5739 PetscFunctionBeginHot; 5740 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5741 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5742 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5743 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5744 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5745 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5746 if (depth == 1 && numFields < 2) { 5747 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5748 PetscFunctionReturn(0); 5749 } 5750 /* Get points */ 5751 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5752 /* Get sizes */ 5753 asize = 0; 5754 for (PetscInt p = 0; p < numPoints*2; p += 2) { 5755 PetscInt dof; 5756 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5757 asize += dof; 5758 } 5759 if (values) { 5760 const PetscScalar *vArray; 5761 PetscInt size; 5762 5763 if (*values) { 5764 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); 5765 } else {ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, values);CHKERRQ(ierr);} 5766 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm);CHKERRQ(ierr); 5767 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5768 /* Get values */ 5769 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values);CHKERRQ(ierr);} 5770 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values);CHKERRQ(ierr);} 5771 if (PetscUnlikely(asize != size)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size); 5772 /* Cleanup array */ 5773 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5774 } 5775 if (csize) *csize = asize; 5776 /* Cleanup points */ 5777 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5778 PetscFunctionReturn(0); 5779 } 5780 5781 PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5782 { 5783 DMLabel depthLabel; 5784 PetscSection clSection; 5785 IS clPoints; 5786 PetscScalar *array; 5787 const PetscScalar *vArray; 5788 PetscInt *points = NULL; 5789 const PetscInt *clp, *perm = NULL; 5790 PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5791 PetscErrorCode ierr; 5792 5793 PetscFunctionBeginHot; 5794 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5795 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5796 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5797 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5798 ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr); 5799 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 5800 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5801 if (mdepth == 1 && numFields < 2) { 5802 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5803 PetscFunctionReturn(0); 5804 } 5805 /* Get points */ 5806 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5807 for (clsize=0,p=0; p<Np; p++) { 5808 PetscInt dof; 5809 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 5810 clsize += dof; 5811 } 5812 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm);CHKERRQ(ierr); 5813 /* Filter points */ 5814 for (p = 0; p < numPoints*2; p += 2) { 5815 PetscInt dep; 5816 5817 ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr); 5818 if (dep != depth) continue; 5819 points[Np*2+0] = points[p]; 5820 points[Np*2+1] = points[p+1]; 5821 ++Np; 5822 } 5823 /* Get array */ 5824 if (!values || !*values) { 5825 PetscInt asize = 0, dof; 5826 5827 for (p = 0; p < Np*2; p += 2) { 5828 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5829 asize += dof; 5830 } 5831 if (!values) { 5832 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5833 if (csize) *csize = asize; 5834 PetscFunctionReturn(0); 5835 } 5836 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 5837 } else { 5838 array = *values; 5839 } 5840 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5841 /* Get values */ 5842 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 5843 else {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);} 5844 /* Cleanup points */ 5845 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5846 /* Cleanup array */ 5847 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5848 if (!*values) { 5849 if (csize) *csize = size; 5850 *values = array; 5851 } else { 5852 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5853 *csize = size; 5854 } 5855 PetscFunctionReturn(0); 5856 } 5857 5858 /*@C 5859 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5860 5861 Not collective 5862 5863 Input Parameters: 5864 + dm - The DM 5865 . section - The section describing the layout in v, or NULL to use the default section 5866 . v - The local vector 5867 . point - The point in the DM 5868 . csize - The number of values in the closure, or NULL 5869 - values - The array of values, which is a borrowed array and should not be freed 5870 5871 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 5872 5873 Fortran Notes: 5874 Since it returns an array, this routine is only available in Fortran 90, and you must 5875 include petsc.h90 in your code. 5876 5877 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5878 5879 Level: intermediate 5880 5881 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5882 @*/ 5883 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5884 { 5885 PetscInt size = 0; 5886 PetscErrorCode ierr; 5887 5888 PetscFunctionBegin; 5889 /* Should work without recalculating size */ 5890 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 5891 *values = NULL; 5892 PetscFunctionReturn(0); 5893 } 5894 5895 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 5896 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5897 5898 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[]) 5899 { 5900 PetscInt cdof; /* The number of constraints on this point */ 5901 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5902 PetscScalar *a; 5903 PetscInt off, cind = 0, k; 5904 PetscErrorCode ierr; 5905 5906 PetscFunctionBegin; 5907 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5908 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5909 a = &array[off]; 5910 if (!cdof || setBC) { 5911 if (clperm) { 5912 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 5913 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5914 } else { 5915 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 5916 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5917 } 5918 } else { 5919 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5920 if (clperm) { 5921 if (perm) {for (k = 0; k < dof; ++k) { 5922 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5923 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5924 } 5925 } else { 5926 for (k = 0; k < dof; ++k) { 5927 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5928 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5929 } 5930 } 5931 } else { 5932 if (perm) { 5933 for (k = 0; k < dof; ++k) { 5934 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5935 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5936 } 5937 } else { 5938 for (k = 0; k < dof; ++k) { 5939 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5940 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5941 } 5942 } 5943 } 5944 } 5945 PetscFunctionReturn(0); 5946 } 5947 5948 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[]) 5949 { 5950 PetscInt cdof; /* The number of constraints on this point */ 5951 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5952 PetscScalar *a; 5953 PetscInt off, cind = 0, k; 5954 PetscErrorCode ierr; 5955 5956 PetscFunctionBegin; 5957 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5958 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5959 a = &array[off]; 5960 if (cdof) { 5961 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5962 if (clperm) { 5963 if (perm) { 5964 for (k = 0; k < dof; ++k) { 5965 if ((cind < cdof) && (k == cdofs[cind])) { 5966 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5967 cind++; 5968 } 5969 } 5970 } else { 5971 for (k = 0; k < dof; ++k) { 5972 if ((cind < cdof) && (k == cdofs[cind])) { 5973 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5974 cind++; 5975 } 5976 } 5977 } 5978 } else { 5979 if (perm) { 5980 for (k = 0; k < dof; ++k) { 5981 if ((cind < cdof) && (k == cdofs[cind])) { 5982 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5983 cind++; 5984 } 5985 } 5986 } else { 5987 for (k = 0; k < dof; ++k) { 5988 if ((cind < cdof) && (k == cdofs[cind])) { 5989 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5990 cind++; 5991 } 5992 } 5993 } 5994 } 5995 } 5996 PetscFunctionReturn(0); 5997 } 5998 5999 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[]) 6000 { 6001 PetscScalar *a; 6002 PetscInt fdof, foff, fcdof, foffset = *offset; 6003 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6004 PetscInt cind = 0, b; 6005 PetscErrorCode ierr; 6006 6007 PetscFunctionBegin; 6008 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6009 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6010 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 6011 a = &array[foff]; 6012 if (!fcdof || setBC) { 6013 if (clperm) { 6014 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 6015 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 6016 } else { 6017 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 6018 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 6019 } 6020 } else { 6021 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6022 if (clperm) { 6023 if (perm) { 6024 for (b = 0; b < fdof; b++) { 6025 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6026 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6027 } 6028 } else { 6029 for (b = 0; b < fdof; b++) { 6030 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6031 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6032 } 6033 } 6034 } else { 6035 if (perm) { 6036 for (b = 0; b < fdof; b++) { 6037 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6038 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6039 } 6040 } else { 6041 for (b = 0; b < fdof; b++) { 6042 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 6043 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6044 } 6045 } 6046 } 6047 } 6048 *offset += fdof; 6049 PetscFunctionReturn(0); 6050 } 6051 6052 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[]) 6053 { 6054 PetscScalar *a; 6055 PetscInt fdof, foff, fcdof, foffset = *offset; 6056 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6057 PetscInt Nc, cind = 0, ncind = 0, b; 6058 PetscBool ncSet, fcSet; 6059 PetscErrorCode ierr; 6060 6061 PetscFunctionBegin; 6062 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 6063 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6064 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 6065 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 6066 a = &array[foff]; 6067 if (fcdof) { 6068 /* We just override fcdof and fcdofs with Ncc and comps */ 6069 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6070 if (clperm) { 6071 if (perm) { 6072 if (comps) { 6073 for (b = 0; b < fdof; b++) { 6074 ncSet = fcSet = PETSC_FALSE; 6075 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6076 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6077 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 6078 } 6079 } else { 6080 for (b = 0; b < fdof; b++) { 6081 if ((cind < fcdof) && (b == fcdofs[cind])) { 6082 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6083 ++cind; 6084 } 6085 } 6086 } 6087 } else { 6088 if (comps) { 6089 for (b = 0; b < fdof; b++) { 6090 ncSet = fcSet = PETSC_FALSE; 6091 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6092 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6093 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 6094 } 6095 } else { 6096 for (b = 0; b < fdof; b++) { 6097 if ((cind < fcdof) && (b == fcdofs[cind])) { 6098 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 6099 ++cind; 6100 } 6101 } 6102 } 6103 } 6104 } else { 6105 if (perm) { 6106 if (comps) { 6107 for (b = 0; b < fdof; b++) { 6108 ncSet = fcSet = PETSC_FALSE; 6109 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6110 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6111 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 6112 } 6113 } else { 6114 for (b = 0; b < fdof; b++) { 6115 if ((cind < fcdof) && (b == fcdofs[cind])) { 6116 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 6117 ++cind; 6118 } 6119 } 6120 } 6121 } else { 6122 if (comps) { 6123 for (b = 0; b < fdof; b++) { 6124 ncSet = fcSet = PETSC_FALSE; 6125 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 6126 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 6127 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 6128 } 6129 } else { 6130 for (b = 0; b < fdof; b++) { 6131 if ((cind < fcdof) && (b == fcdofs[cind])) { 6132 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 6133 ++cind; 6134 } 6135 } 6136 } 6137 } 6138 } 6139 } 6140 *offset += fdof; 6141 PetscFunctionReturn(0); 6142 } 6143 6144 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6145 { 6146 PetscScalar *array; 6147 const PetscInt *cone, *coneO; 6148 PetscInt pStart, pEnd, p, numPoints, off, dof; 6149 PetscErrorCode ierr; 6150 6151 PetscFunctionBeginHot; 6152 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6153 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 6154 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 6155 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 6156 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6157 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6158 const PetscInt cp = !p ? point : cone[p-1]; 6159 const PetscInt o = !p ? 0 : coneO[p-1]; 6160 6161 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 6162 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 6163 /* ADD_VALUES */ 6164 { 6165 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6166 PetscScalar *a; 6167 PetscInt cdof, coff, cind = 0, k; 6168 6169 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 6170 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 6171 a = &array[coff]; 6172 if (!cdof) { 6173 if (o >= 0) { 6174 for (k = 0; k < dof; ++k) { 6175 a[k] += values[off+k]; 6176 } 6177 } else { 6178 for (k = 0; k < dof; ++k) { 6179 a[k] += values[off+dof-k-1]; 6180 } 6181 } 6182 } else { 6183 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 6184 if (o >= 0) { 6185 for (k = 0; k < dof; ++k) { 6186 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6187 a[k] += values[off+k]; 6188 } 6189 } else { 6190 for (k = 0; k < dof; ++k) { 6191 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6192 a[k] += values[off+dof-k-1]; 6193 } 6194 } 6195 } 6196 } 6197 } 6198 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6199 PetscFunctionReturn(0); 6200 } 6201 6202 /*@C 6203 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6204 6205 Not collective 6206 6207 Input Parameters: 6208 + dm - The DM 6209 . section - The section describing the layout in v, or NULL to use the default section 6210 . v - The local vector 6211 . point - The point in the DM 6212 . values - The array of values 6213 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 6214 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 6215 6216 Fortran Notes: 6217 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6218 6219 Level: intermediate 6220 6221 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6222 @*/ 6223 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6224 { 6225 PetscSection clSection; 6226 IS clPoints; 6227 PetscScalar *array; 6228 PetscInt *points = NULL; 6229 const PetscInt *clp, *clperm = NULL; 6230 PetscInt depth, numFields, numPoints, p, clsize; 6231 PetscErrorCode ierr; 6232 6233 PetscFunctionBeginHot; 6234 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6235 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6236 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6237 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6238 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6239 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6240 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 6241 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 6242 PetscFunctionReturn(0); 6243 } 6244 /* Get points */ 6245 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6246 for (clsize=0,p=0; p<numPoints; p++) { 6247 PetscInt dof; 6248 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 6249 clsize += dof; 6250 } 6251 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 6252 /* Get array */ 6253 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6254 /* Get values */ 6255 if (numFields > 0) { 6256 PetscInt offset = 0, f; 6257 for (f = 0; f < numFields; ++f) { 6258 const PetscInt **perms = NULL; 6259 const PetscScalar **flips = NULL; 6260 6261 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6262 switch (mode) { 6263 case INSERT_VALUES: 6264 for (p = 0; p < numPoints; p++) { 6265 const PetscInt point = points[2*p]; 6266 const PetscInt *perm = perms ? perms[p] : NULL; 6267 const PetscScalar *flip = flips ? flips[p] : NULL; 6268 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6269 } break; 6270 case INSERT_ALL_VALUES: 6271 for (p = 0; p < numPoints; p++) { 6272 const PetscInt point = points[2*p]; 6273 const PetscInt *perm = perms ? perms[p] : NULL; 6274 const PetscScalar *flip = flips ? flips[p] : NULL; 6275 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6276 } break; 6277 case INSERT_BC_VALUES: 6278 for (p = 0; p < numPoints; p++) { 6279 const PetscInt point = points[2*p]; 6280 const PetscInt *perm = perms ? perms[p] : NULL; 6281 const PetscScalar *flip = flips ? flips[p] : NULL; 6282 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6283 } break; 6284 case ADD_VALUES: 6285 for (p = 0; p < numPoints; p++) { 6286 const PetscInt point = points[2*p]; 6287 const PetscInt *perm = perms ? perms[p] : NULL; 6288 const PetscScalar *flip = flips ? flips[p] : NULL; 6289 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6290 } break; 6291 case ADD_ALL_VALUES: 6292 for (p = 0; p < numPoints; p++) { 6293 const PetscInt point = points[2*p]; 6294 const PetscInt *perm = perms ? perms[p] : NULL; 6295 const PetscScalar *flip = flips ? flips[p] : NULL; 6296 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6297 } break; 6298 case ADD_BC_VALUES: 6299 for (p = 0; p < numPoints; p++) { 6300 const PetscInt point = points[2*p]; 6301 const PetscInt *perm = perms ? perms[p] : NULL; 6302 const PetscScalar *flip = flips ? flips[p] : NULL; 6303 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6304 } break; 6305 default: 6306 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6307 } 6308 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6309 } 6310 } else { 6311 PetscInt dof, off; 6312 const PetscInt **perms = NULL; 6313 const PetscScalar **flips = NULL; 6314 6315 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6316 switch (mode) { 6317 case INSERT_VALUES: 6318 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6319 const PetscInt point = points[2*p]; 6320 const PetscInt *perm = perms ? perms[p] : NULL; 6321 const PetscScalar *flip = flips ? flips[p] : NULL; 6322 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6323 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6324 } break; 6325 case INSERT_ALL_VALUES: 6326 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6327 const PetscInt point = points[2*p]; 6328 const PetscInt *perm = perms ? perms[p] : NULL; 6329 const PetscScalar *flip = flips ? flips[p] : NULL; 6330 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6331 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6332 } break; 6333 case INSERT_BC_VALUES: 6334 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6335 const PetscInt point = points[2*p]; 6336 const PetscInt *perm = perms ? perms[p] : NULL; 6337 const PetscScalar *flip = flips ? flips[p] : NULL; 6338 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6339 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6340 } break; 6341 case ADD_VALUES: 6342 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6343 const PetscInt point = points[2*p]; 6344 const PetscInt *perm = perms ? perms[p] : NULL; 6345 const PetscScalar *flip = flips ? flips[p] : NULL; 6346 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6347 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6348 } break; 6349 case ADD_ALL_VALUES: 6350 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6351 const PetscInt point = points[2*p]; 6352 const PetscInt *perm = perms ? perms[p] : NULL; 6353 const PetscScalar *flip = flips ? flips[p] : NULL; 6354 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6355 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6356 } break; 6357 case ADD_BC_VALUES: 6358 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6359 const PetscInt point = points[2*p]; 6360 const PetscInt *perm = perms ? perms[p] : NULL; 6361 const PetscScalar *flip = flips ? flips[p] : NULL; 6362 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6363 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6364 } break; 6365 default: 6366 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6367 } 6368 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6369 } 6370 /* Cleanup points */ 6371 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6372 /* Cleanup array */ 6373 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6374 PetscFunctionReturn(0); 6375 } 6376 6377 /* Check whether the given point is in the label. If not, update the offset to skip this point */ 6378 PETSC_STATIC_INLINE PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 6379 { 6380 PetscFunctionBegin; 6381 if (label) { 6382 PetscInt val, fdof; 6383 PetscErrorCode ierr; 6384 6385 /* There is a problem with this: 6386 Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that 6387 touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell. 6388 Thus I am only going to check val != -1, not val != labelId 6389 */ 6390 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 6391 if (val < 0) { 6392 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6393 *offset += fdof; 6394 PetscFunctionReturn(1); 6395 } 6396 } 6397 PetscFunctionReturn(0); 6398 } 6399 6400 /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 6401 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) 6402 { 6403 PetscSection clSection; 6404 IS clPoints; 6405 PetscScalar *array; 6406 PetscInt *points = NULL; 6407 const PetscInt *clp; 6408 PetscInt numFields, numPoints, p; 6409 PetscInt offset = 0, f; 6410 PetscErrorCode ierr; 6411 6412 PetscFunctionBeginHot; 6413 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6414 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6415 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6416 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6417 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6418 /* Get points */ 6419 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6420 /* Get array */ 6421 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6422 /* Get values */ 6423 for (f = 0; f < numFields; ++f) { 6424 const PetscInt **perms = NULL; 6425 const PetscScalar **flips = NULL; 6426 6427 if (!fieldActive[f]) { 6428 for (p = 0; p < numPoints*2; p += 2) { 6429 PetscInt fdof; 6430 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6431 offset += fdof; 6432 } 6433 continue; 6434 } 6435 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6436 switch (mode) { 6437 case INSERT_VALUES: 6438 for (p = 0; p < numPoints; p++) { 6439 const PetscInt point = points[2*p]; 6440 const PetscInt *perm = perms ? perms[p] : NULL; 6441 const PetscScalar *flip = flips ? flips[p] : NULL; 6442 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6443 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array); 6444 } break; 6445 case INSERT_ALL_VALUES: 6446 for (p = 0; p < numPoints; p++) { 6447 const PetscInt point = points[2*p]; 6448 const PetscInt *perm = perms ? perms[p] : NULL; 6449 const PetscScalar *flip = flips ? flips[p] : NULL; 6450 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6451 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array); 6452 } break; 6453 case INSERT_BC_VALUES: 6454 for (p = 0; p < numPoints; p++) { 6455 const PetscInt point = points[2*p]; 6456 const PetscInt *perm = perms ? perms[p] : NULL; 6457 const PetscScalar *flip = flips ? flips[p] : NULL; 6458 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6459 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array); 6460 } break; 6461 case ADD_VALUES: 6462 for (p = 0; p < numPoints; p++) { 6463 const PetscInt point = points[2*p]; 6464 const PetscInt *perm = perms ? perms[p] : NULL; 6465 const PetscScalar *flip = flips ? flips[p] : NULL; 6466 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6467 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array); 6468 } break; 6469 case ADD_ALL_VALUES: 6470 for (p = 0; p < numPoints; p++) { 6471 const PetscInt point = points[2*p]; 6472 const PetscInt *perm = perms ? perms[p] : NULL; 6473 const PetscScalar *flip = flips ? flips[p] : NULL; 6474 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6475 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array); 6476 } break; 6477 default: 6478 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6479 } 6480 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6481 } 6482 /* Cleanup points */ 6483 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6484 /* Cleanup array */ 6485 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6486 PetscFunctionReturn(0); 6487 } 6488 6489 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6490 { 6491 PetscMPIInt rank; 6492 PetscInt i, j; 6493 PetscErrorCode ierr; 6494 6495 PetscFunctionBegin; 6496 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr); 6497 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 6498 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 6499 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 6500 numCIndices = numCIndices ? numCIndices : numRIndices; 6501 if (!values) PetscFunctionReturn(0); 6502 for (i = 0; i < numRIndices; i++) { 6503 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 6504 for (j = 0; j < numCIndices; j++) { 6505 #if defined(PETSC_USE_COMPLEX) 6506 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 6507 #else 6508 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 6509 #endif 6510 } 6511 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6512 } 6513 PetscFunctionReturn(0); 6514 } 6515 6516 /* 6517 DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 6518 6519 Input Parameters: 6520 + section - The section for this data layout 6521 . islocal - Is the section (and thus indices being requested) local or global? 6522 . point - The point contributing dofs with these indices 6523 . off - The global offset of this point 6524 . loff - The local offset of each field 6525 . setBC - The flag determining whether to include indices of boundary values 6526 . perm - A permutation of the dofs on this point, or NULL 6527 - indperm - A permutation of the entire indices array, or NULL 6528 6529 Output Parameter: 6530 . indices - Indices for dofs on this point 6531 6532 Level: developer 6533 6534 Note: The indices could be local or global, depending on the value of 'off'. 6535 */ 6536 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6537 { 6538 PetscInt dof; /* The number of unknowns on this point */ 6539 PetscInt cdof; /* The number of constraints on this point */ 6540 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6541 PetscInt cind = 0, k; 6542 PetscErrorCode ierr; 6543 6544 PetscFunctionBegin; 6545 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6546 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6547 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6548 if (!cdof || setBC) { 6549 for (k = 0; k < dof; ++k) { 6550 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6551 const PetscInt ind = indperm ? indperm[preind] : preind; 6552 6553 indices[ind] = off + k; 6554 } 6555 } else { 6556 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6557 for (k = 0; k < dof; ++k) { 6558 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6559 const PetscInt ind = indperm ? indperm[preind] : preind; 6560 6561 if ((cind < cdof) && (k == cdofs[cind])) { 6562 /* Insert check for returning constrained indices */ 6563 indices[ind] = -(off+k+1); 6564 ++cind; 6565 } else { 6566 indices[ind] = off + k - (islocal ? 0 : cind); 6567 } 6568 } 6569 } 6570 *loff += dof; 6571 PetscFunctionReturn(0); 6572 } 6573 6574 /* 6575 DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 6576 6577 Input Parameters: 6578 + section - a section (global or local) 6579 - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 6580 . point - point within section 6581 . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 6582 . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 6583 . setBC - identify constrained (boundary condition) points via involution. 6584 . perms - perms[f][permsoff][:] is a permutation of dofs within each field 6585 . permsoff - offset 6586 - indperm - index permutation 6587 6588 Output Parameter: 6589 . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 6590 . indices - array to hold indices (as defined by section) of each dof associated with point 6591 6592 Notes: 6593 If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 6594 If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 6595 in the local vector. 6596 6597 If section is global and setBC=false, the indices for constrained points are negative (and their value is not 6598 significant). It is invalid to call with a global section and setBC=true. 6599 6600 Developer Note: 6601 The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 6602 in the future, global sections may have fields set, in which case we could pass the global section and obtain the 6603 offset could be obtained from the section instead of passing it explicitly as we do now. 6604 6605 Example: 6606 Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 6607 When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 6608 Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 6609 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. 6610 6611 Level: developer 6612 */ 6613 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[]) 6614 { 6615 PetscInt numFields, foff, f; 6616 PetscErrorCode ierr; 6617 6618 PetscFunctionBegin; 6619 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6620 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6621 for (f = 0, foff = 0; f < numFields; ++f) { 6622 PetscInt fdof, cfdof; 6623 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6624 PetscInt cind = 0, b; 6625 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6626 6627 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6628 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6629 if (!cfdof || setBC) { 6630 for (b = 0; b < fdof; ++b) { 6631 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6632 const PetscInt ind = indperm ? indperm[preind] : preind; 6633 6634 indices[ind] = off+foff+b; 6635 } 6636 } else { 6637 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6638 for (b = 0; b < fdof; ++b) { 6639 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6640 const PetscInt ind = indperm ? indperm[preind] : preind; 6641 6642 if ((cind < cfdof) && (b == fcdofs[cind])) { 6643 indices[ind] = -(off+foff+b+1); 6644 ++cind; 6645 } else { 6646 indices[ind] = off + foff + b - (islocal ? 0 : cind); 6647 } 6648 } 6649 } 6650 foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6651 foffs[f] += fdof; 6652 } 6653 PetscFunctionReturn(0); 6654 } 6655 6656 /* 6657 This version believes the globalSection offsets for each field, rather than just the point offset 6658 6659 . foffs - The offset into 'indices' for each field, since it is segregated by field 6660 6661 Notes: 6662 The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6663 Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 6664 */ 6665 static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 6666 { 6667 PetscInt numFields, foff, f; 6668 PetscErrorCode ierr; 6669 6670 PetscFunctionBegin; 6671 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6672 for (f = 0; f < numFields; ++f) { 6673 PetscInt fdof, cfdof; 6674 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6675 PetscInt cind = 0, b; 6676 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6677 6678 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6679 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6680 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 6681 if (!cfdof) { 6682 for (b = 0; b < fdof; ++b) { 6683 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6684 const PetscInt ind = indperm ? indperm[preind] : preind; 6685 6686 indices[ind] = foff+b; 6687 } 6688 } else { 6689 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6690 for (b = 0; b < fdof; ++b) { 6691 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6692 const PetscInt ind = indperm ? indperm[preind] : preind; 6693 6694 if ((cind < cfdof) && (b == fcdofs[cind])) { 6695 indices[ind] = -(foff+b+1); 6696 ++cind; 6697 } else { 6698 indices[ind] = foff+b-cind; 6699 } 6700 } 6701 } 6702 foffs[f] += fdof; 6703 } 6704 PetscFunctionReturn(0); 6705 } 6706 6707 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) 6708 { 6709 Mat cMat; 6710 PetscSection aSec, cSec; 6711 IS aIS; 6712 PetscInt aStart = -1, aEnd = -1; 6713 const PetscInt *anchors; 6714 PetscInt numFields, f, p, q, newP = 0; 6715 PetscInt newNumPoints = 0, newNumIndices = 0; 6716 PetscInt *newPoints, *indices, *newIndices; 6717 PetscInt maxAnchor, maxDof; 6718 PetscInt newOffsets[32]; 6719 PetscInt *pointMatOffsets[32]; 6720 PetscInt *newPointOffsets[32]; 6721 PetscScalar *pointMat[32]; 6722 PetscScalar *newValues=NULL,*tmpValues; 6723 PetscBool anyConstrained = PETSC_FALSE; 6724 PetscErrorCode ierr; 6725 6726 PetscFunctionBegin; 6727 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6728 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6729 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6730 6731 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6732 /* if there are point-to-point constraints */ 6733 if (aSec) { 6734 ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr); 6735 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6736 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 6737 /* figure out how many points are going to be in the new element matrix 6738 * (we allow double counting, because it's all just going to be summed 6739 * into the global matrix anyway) */ 6740 for (p = 0; p < 2*numPoints; p+=2) { 6741 PetscInt b = points[p]; 6742 PetscInt bDof = 0, bSecDof; 6743 6744 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6745 if (!bSecDof) { 6746 continue; 6747 } 6748 if (b >= aStart && b < aEnd) { 6749 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 6750 } 6751 if (bDof) { 6752 /* this point is constrained */ 6753 /* it is going to be replaced by its anchors */ 6754 PetscInt bOff, q; 6755 6756 anyConstrained = PETSC_TRUE; 6757 newNumPoints += bDof; 6758 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 6759 for (q = 0; q < bDof; q++) { 6760 PetscInt a = anchors[bOff + q]; 6761 PetscInt aDof; 6762 6763 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6764 newNumIndices += aDof; 6765 for (f = 0; f < numFields; ++f) { 6766 PetscInt fDof; 6767 6768 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 6769 newOffsets[f+1] += fDof; 6770 } 6771 } 6772 } 6773 else { 6774 /* this point is not constrained */ 6775 newNumPoints++; 6776 newNumIndices += bSecDof; 6777 for (f = 0; f < numFields; ++f) { 6778 PetscInt fDof; 6779 6780 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6781 newOffsets[f+1] += fDof; 6782 } 6783 } 6784 } 6785 } 6786 if (!anyConstrained) { 6787 if (outNumPoints) *outNumPoints = 0; 6788 if (outNumIndices) *outNumIndices = 0; 6789 if (outPoints) *outPoints = NULL; 6790 if (outValues) *outValues = NULL; 6791 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6792 PetscFunctionReturn(0); 6793 } 6794 6795 if (outNumPoints) *outNumPoints = newNumPoints; 6796 if (outNumIndices) *outNumIndices = newNumIndices; 6797 6798 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6799 6800 if (!outPoints && !outValues) { 6801 if (offsets) { 6802 for (f = 0; f <= numFields; f++) { 6803 offsets[f] = newOffsets[f]; 6804 } 6805 } 6806 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6807 PetscFunctionReturn(0); 6808 } 6809 6810 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 6811 6812 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 6813 6814 /* workspaces */ 6815 if (numFields) { 6816 for (f = 0; f < numFields; f++) { 6817 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 6818 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6819 } 6820 } 6821 else { 6822 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 6823 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6824 } 6825 6826 /* get workspaces for the point-to-point matrices */ 6827 if (numFields) { 6828 PetscInt totalOffset, totalMatOffset; 6829 6830 for (p = 0; p < numPoints; p++) { 6831 PetscInt b = points[2*p]; 6832 PetscInt bDof = 0, bSecDof; 6833 6834 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6835 if (!bSecDof) { 6836 for (f = 0; f < numFields; f++) { 6837 newPointOffsets[f][p + 1] = 0; 6838 pointMatOffsets[f][p + 1] = 0; 6839 } 6840 continue; 6841 } 6842 if (b >= aStart && b < aEnd) { 6843 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6844 } 6845 if (bDof) { 6846 for (f = 0; f < numFields; f++) { 6847 PetscInt fDof, q, bOff, allFDof = 0; 6848 6849 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6850 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6851 for (q = 0; q < bDof; q++) { 6852 PetscInt a = anchors[bOff + q]; 6853 PetscInt aFDof; 6854 6855 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 6856 allFDof += aFDof; 6857 } 6858 newPointOffsets[f][p+1] = allFDof; 6859 pointMatOffsets[f][p+1] = fDof * allFDof; 6860 } 6861 } 6862 else { 6863 for (f = 0; f < numFields; f++) { 6864 PetscInt fDof; 6865 6866 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6867 newPointOffsets[f][p+1] = fDof; 6868 pointMatOffsets[f][p+1] = 0; 6869 } 6870 } 6871 } 6872 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 6873 newPointOffsets[f][0] = totalOffset; 6874 pointMatOffsets[f][0] = totalMatOffset; 6875 for (p = 0; p < numPoints; p++) { 6876 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6877 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6878 } 6879 totalOffset = newPointOffsets[f][numPoints]; 6880 totalMatOffset = pointMatOffsets[f][numPoints]; 6881 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 6882 } 6883 } 6884 else { 6885 for (p = 0; p < numPoints; p++) { 6886 PetscInt b = points[2*p]; 6887 PetscInt bDof = 0, bSecDof; 6888 6889 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6890 if (!bSecDof) { 6891 newPointOffsets[0][p + 1] = 0; 6892 pointMatOffsets[0][p + 1] = 0; 6893 continue; 6894 } 6895 if (b >= aStart && b < aEnd) { 6896 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6897 } 6898 if (bDof) { 6899 PetscInt bOff, q, allDof = 0; 6900 6901 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6902 for (q = 0; q < bDof; q++) { 6903 PetscInt a = anchors[bOff + q], aDof; 6904 6905 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 6906 allDof += aDof; 6907 } 6908 newPointOffsets[0][p+1] = allDof; 6909 pointMatOffsets[0][p+1] = bSecDof * allDof; 6910 } 6911 else { 6912 newPointOffsets[0][p+1] = bSecDof; 6913 pointMatOffsets[0][p+1] = 0; 6914 } 6915 } 6916 newPointOffsets[0][0] = 0; 6917 pointMatOffsets[0][0] = 0; 6918 for (p = 0; p < numPoints; p++) { 6919 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6920 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6921 } 6922 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 6923 } 6924 6925 /* output arrays */ 6926 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6927 6928 /* get the point-to-point matrices; construct newPoints */ 6929 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 6930 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6931 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 6932 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 6933 if (numFields) { 6934 for (p = 0, newP = 0; p < numPoints; p++) { 6935 PetscInt b = points[2*p]; 6936 PetscInt o = points[2*p+1]; 6937 PetscInt bDof = 0, bSecDof; 6938 6939 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6940 if (!bSecDof) { 6941 continue; 6942 } 6943 if (b >= aStart && b < aEnd) { 6944 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6945 } 6946 if (bDof) { 6947 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6948 6949 fStart[0] = 0; 6950 fEnd[0] = 0; 6951 for (f = 0; f < numFields; f++) { 6952 PetscInt fDof; 6953 6954 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 6955 fStart[f+1] = fStart[f] + fDof; 6956 fEnd[f+1] = fStart[f+1]; 6957 } 6958 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6959 ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 6960 6961 fAnchorStart[0] = 0; 6962 fAnchorEnd[0] = 0; 6963 for (f = 0; f < numFields; f++) { 6964 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 6965 6966 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 6967 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 6968 } 6969 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6970 for (q = 0; q < bDof; q++) { 6971 PetscInt a = anchors[bOff + q], aOff; 6972 6973 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6974 newPoints[2*(newP + q)] = a; 6975 newPoints[2*(newP + q) + 1] = 0; 6976 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 6977 ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 6978 } 6979 newP += bDof; 6980 6981 if (outValues) { 6982 /* get the point-to-point submatrix */ 6983 for (f = 0; f < numFields; f++) { 6984 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 6985 } 6986 } 6987 } 6988 else { 6989 newPoints[2 * newP] = b; 6990 newPoints[2 * newP + 1] = o; 6991 newP++; 6992 } 6993 } 6994 } else { 6995 for (p = 0; p < numPoints; p++) { 6996 PetscInt b = points[2*p]; 6997 PetscInt o = points[2*p+1]; 6998 PetscInt bDof = 0, bSecDof; 6999 7000 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 7001 if (!bSecDof) { 7002 continue; 7003 } 7004 if (b >= aStart && b < aEnd) { 7005 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 7006 } 7007 if (bDof) { 7008 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7009 7010 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 7011 ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 7012 7013 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 7014 for (q = 0; q < bDof; q++) { 7015 PetscInt a = anchors[bOff + q], aOff; 7016 7017 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 7018 7019 newPoints[2*(newP + q)] = a; 7020 newPoints[2*(newP + q) + 1] = 0; 7021 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 7022 ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 7023 } 7024 newP += bDof; 7025 7026 /* get the point-to-point submatrix */ 7027 if (outValues) { 7028 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 7029 } 7030 } 7031 else { 7032 newPoints[2 * newP] = b; 7033 newPoints[2 * newP + 1] = o; 7034 newP++; 7035 } 7036 } 7037 } 7038 7039 if (outValues) { 7040 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7041 ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr); 7042 /* multiply constraints on the right */ 7043 if (numFields) { 7044 for (f = 0; f < numFields; f++) { 7045 PetscInt oldOff = offsets[f]; 7046 7047 for (p = 0; p < numPoints; p++) { 7048 PetscInt cStart = newPointOffsets[f][p]; 7049 PetscInt b = points[2 * p]; 7050 PetscInt c, r, k; 7051 PetscInt dof; 7052 7053 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7054 if (!dof) { 7055 continue; 7056 } 7057 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7058 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 7059 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7060 7061 for (r = 0; r < numIndices; r++) { 7062 for (c = 0; c < nCols; c++) { 7063 for (k = 0; k < dof; k++) { 7064 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7065 } 7066 } 7067 } 7068 } 7069 else { 7070 /* copy this column as is */ 7071 for (r = 0; r < numIndices; r++) { 7072 for (c = 0; c < dof; c++) { 7073 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7074 } 7075 } 7076 } 7077 oldOff += dof; 7078 } 7079 } 7080 } 7081 else { 7082 PetscInt oldOff = 0; 7083 for (p = 0; p < numPoints; p++) { 7084 PetscInt cStart = newPointOffsets[0][p]; 7085 PetscInt b = points[2 * p]; 7086 PetscInt c, r, k; 7087 PetscInt dof; 7088 7089 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7090 if (!dof) { 7091 continue; 7092 } 7093 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7094 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 7095 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7096 7097 for (r = 0; r < numIndices; r++) { 7098 for (c = 0; c < nCols; c++) { 7099 for (k = 0; k < dof; k++) { 7100 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7101 } 7102 } 7103 } 7104 } 7105 else { 7106 /* copy this column as is */ 7107 for (r = 0; r < numIndices; r++) { 7108 for (c = 0; c < dof; c++) { 7109 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7110 } 7111 } 7112 } 7113 oldOff += dof; 7114 } 7115 } 7116 7117 if (multiplyLeft) { 7118 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 7119 ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr); 7120 /* multiply constraints transpose on the left */ 7121 if (numFields) { 7122 for (f = 0; f < numFields; f++) { 7123 PetscInt oldOff = offsets[f]; 7124 7125 for (p = 0; p < numPoints; p++) { 7126 PetscInt rStart = newPointOffsets[f][p]; 7127 PetscInt b = points[2 * p]; 7128 PetscInt c, r, k; 7129 PetscInt dof; 7130 7131 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 7132 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7133 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 7134 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7135 7136 for (r = 0; r < nRows; r++) { 7137 for (c = 0; c < newNumIndices; c++) { 7138 for (k = 0; k < dof; k++) { 7139 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7140 } 7141 } 7142 } 7143 } 7144 else { 7145 /* copy this row as is */ 7146 for (r = 0; r < dof; r++) { 7147 for (c = 0; c < newNumIndices; c++) { 7148 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7149 } 7150 } 7151 } 7152 oldOff += dof; 7153 } 7154 } 7155 } 7156 else { 7157 PetscInt oldOff = 0; 7158 7159 for (p = 0; p < numPoints; p++) { 7160 PetscInt rStart = newPointOffsets[0][p]; 7161 PetscInt b = points[2 * p]; 7162 PetscInt c, r, k; 7163 PetscInt dof; 7164 7165 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 7166 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7167 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 7168 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7169 7170 for (r = 0; r < nRows; r++) { 7171 for (c = 0; c < newNumIndices; c++) { 7172 for (k = 0; k < dof; k++) { 7173 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7174 } 7175 } 7176 } 7177 } 7178 else { 7179 /* copy this row as is */ 7180 for (r = 0; r < dof; r++) { 7181 for (c = 0; c < newNumIndices; c++) { 7182 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7183 } 7184 } 7185 } 7186 oldOff += dof; 7187 } 7188 } 7189 7190 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7191 } 7192 else { 7193 newValues = tmpValues; 7194 } 7195 } 7196 7197 /* clean up */ 7198 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 7199 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 7200 7201 if (numFields) { 7202 for (f = 0; f < numFields; f++) { 7203 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 7204 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 7205 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 7206 } 7207 } 7208 else { 7209 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 7210 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 7211 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 7212 } 7213 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7214 7215 /* output */ 7216 if (outPoints) { 7217 *outPoints = newPoints; 7218 } 7219 else { 7220 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 7221 } 7222 if (outValues) { 7223 *outValues = newValues; 7224 } 7225 for (f = 0; f <= numFields; f++) { 7226 offsets[f] = newOffsets[f]; 7227 } 7228 PetscFunctionReturn(0); 7229 } 7230 7231 /*@C 7232 DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 7233 7234 Not collective 7235 7236 Input Parameters: 7237 + dm - The DM 7238 . section - The PetscSection describing the points (a local section) 7239 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7240 . point - The point defining the closure 7241 - useClPerm - Use the closure point permutation if available 7242 7243 Output Parameters: 7244 + numIndices - The number of dof indices in the closure of point with the input sections 7245 . indices - The dof indices 7246 . outOffsets - Array to write the field offsets into, or NULL 7247 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7248 7249 Notes: 7250 Must call DMPlexRestoreClosureIndices() to free allocated memory 7251 7252 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7253 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7254 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7255 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7256 indices (with the above semantics) are implied. 7257 7258 Level: advanced 7259 7260 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7261 @*/ 7262 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7263 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7264 { 7265 /* Closure ordering */ 7266 PetscSection clSection; 7267 IS clPoints; 7268 const PetscInt *clp; 7269 PetscInt *points; 7270 const PetscInt *clperm = NULL; 7271 /* Dof permutation and sign flips */ 7272 const PetscInt **perms[32] = {NULL}; 7273 const PetscScalar **flips[32] = {NULL}; 7274 PetscScalar *valCopy = NULL; 7275 /* Hanging node constraints */ 7276 PetscInt *pointsC = NULL; 7277 PetscScalar *valuesC = NULL; 7278 PetscInt NclC, NiC; 7279 7280 PetscInt *idx; 7281 PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 7282 PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 7283 PetscErrorCode ierr; 7284 7285 PetscFunctionBeginHot; 7286 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7287 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7288 PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7289 if (numIndices) PetscValidPointer(numIndices, 6); 7290 if (indices) PetscValidPointer(indices, 7); 7291 if (outOffsets) PetscValidPointer(outOffsets, 8); 7292 if (values) PetscValidPointer(values, 9); 7293 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 7294 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 7295 ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 7296 /* 1) Get points in closure */ 7297 ierr = DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7298 if (useClPerm) { 7299 PetscInt depth, clsize; 7300 ierr = DMPlexGetPointDepth(dm, point, &depth);CHKERRQ(ierr); 7301 for (clsize=0,p=0; p<Ncl; p++) { 7302 PetscInt dof; 7303 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 7304 clsize += dof; 7305 } 7306 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 7307 } 7308 /* 2) Get number of indices on these points and field offsets from section */ 7309 for (p = 0; p < Ncl*2; p += 2) { 7310 PetscInt dof, fdof; 7311 7312 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7313 for (f = 0; f < Nf; ++f) { 7314 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7315 offsets[f+1] += fdof; 7316 } 7317 Ni += dof; 7318 } 7319 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 7320 if (Nf && offsets[Nf] != Ni) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni); 7321 /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 7322 for (f = 0; f < PetscMax(1, Nf); ++f) { 7323 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7324 else {ierr = PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7325 /* may need to apply sign changes to the element matrix */ 7326 if (values && flips[f]) { 7327 PetscInt foffset = offsets[f]; 7328 7329 for (p = 0; p < Ncl; ++p) { 7330 PetscInt pnt = points[2*p], fdof; 7331 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 7332 7333 if (!Nf) {ierr = PetscSectionGetDof(section, pnt, &fdof);CHKERRQ(ierr);} 7334 else {ierr = PetscSectionGetFieldDof(section, pnt, f, &fdof);CHKERRQ(ierr);} 7335 if (flip) { 7336 PetscInt i, j, k; 7337 7338 if (!valCopy) { 7339 ierr = DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr); 7340 for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 7341 *values = valCopy; 7342 } 7343 for (i = 0; i < fdof; ++i) { 7344 PetscScalar fval = flip[i]; 7345 7346 for (k = 0; k < Ni; ++k) { 7347 valCopy[Ni * (foffset + i) + k] *= fval; 7348 valCopy[Ni * k + (foffset + i)] *= fval; 7349 } 7350 } 7351 } 7352 foffset += fdof; 7353 } 7354 } 7355 } 7356 /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 7357 ierr = DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 7358 if (NclC) { 7359 if (valCopy) {ierr = DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);} 7360 for (f = 0; f < PetscMax(1, Nf); ++f) { 7361 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7362 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7363 } 7364 for (f = 0; f < PetscMax(1, Nf); ++f) { 7365 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7366 else {ierr = PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7367 } 7368 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7369 Ncl = NclC; 7370 Ni = NiC; 7371 points = pointsC; 7372 if (values) *values = valuesC; 7373 } 7374 /* 5) Calculate indices */ 7375 ierr = DMGetWorkArray(dm, Ni, MPIU_INT, &idx);CHKERRQ(ierr); 7376 if (Nf) { 7377 PetscInt idxOff; 7378 PetscBool useFieldOffsets; 7379 7380 if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 7381 ierr = PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets);CHKERRQ(ierr); 7382 if (useFieldOffsets) { 7383 for (p = 0; p < Ncl; ++p) { 7384 const PetscInt pnt = points[p*2]; 7385 7386 ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx);CHKERRQ(ierr); 7387 } 7388 } else { 7389 for (p = 0; p < Ncl; ++p) { 7390 const PetscInt pnt = points[p*2]; 7391 7392 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7393 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7394 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 7395 * global section. */ 7396 ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx);CHKERRQ(ierr); 7397 } 7398 } 7399 } else { 7400 PetscInt off = 0, idxOff; 7401 7402 for (p = 0; p < Ncl; ++p) { 7403 const PetscInt pnt = points[p*2]; 7404 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 7405 7406 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7407 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7408 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 7409 ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx);CHKERRQ(ierr); 7410 } 7411 } 7412 /* 6) Cleanup */ 7413 for (f = 0; f < PetscMax(1, Nf); ++f) { 7414 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7415 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7416 } 7417 if (NclC) { 7418 ierr = DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC);CHKERRQ(ierr); 7419 } else { 7420 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7421 } 7422 7423 if (numIndices) *numIndices = Ni; 7424 if (indices) *indices = idx; 7425 PetscFunctionReturn(0); 7426 } 7427 7428 /*@C 7429 DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 7430 7431 Not collective 7432 7433 Input Parameters: 7434 + dm - The DM 7435 . section - The PetscSection describing the points (a local section) 7436 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7437 . point - The point defining the closure 7438 - useClPerm - Use the closure point permutation if available 7439 7440 Output Parameters: 7441 + numIndices - The number of dof indices in the closure of point with the input sections 7442 . indices - The dof indices 7443 . outOffsets - Array to write the field offsets into, or NULL 7444 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7445 7446 Notes: 7447 If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 7448 7449 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7450 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7451 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7452 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7453 indices (with the above semantics) are implied. 7454 7455 Level: advanced 7456 7457 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7458 @*/ 7459 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7460 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7461 { 7462 PetscErrorCode ierr; 7463 7464 PetscFunctionBegin; 7465 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7466 PetscValidPointer(indices, 7); 7467 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 7468 PetscFunctionReturn(0); 7469 } 7470 7471 /*@C 7472 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 7473 7474 Not collective 7475 7476 Input Parameters: 7477 + dm - The DM 7478 . section - The section describing the layout in v, or NULL to use the default section 7479 . globalSection - The section describing the layout in v, or NULL to use the default global section 7480 . A - The matrix 7481 . point - The point in the DM 7482 . values - The array of values 7483 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7484 7485 Fortran Notes: 7486 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 7487 7488 Level: intermediate 7489 7490 .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7491 @*/ 7492 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7493 { 7494 DM_Plex *mesh = (DM_Plex*) dm->data; 7495 PetscInt *indices; 7496 PetscInt numIndices; 7497 const PetscScalar *valuesOrig = values; 7498 PetscErrorCode ierr; 7499 7500 PetscFunctionBegin; 7501 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7502 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 7503 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7504 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 7505 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 7506 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7507 7508 ierr = DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7509 7510 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 7511 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7512 if (ierr) { 7513 PetscMPIInt rank; 7514 PetscErrorCode ierr2; 7515 7516 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7517 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7518 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 7519 ierr2 = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7520 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7521 SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values"); 7522 } 7523 if (mesh->printFEM > 1) { 7524 PetscInt i; 7525 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 7526 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 7527 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7528 } 7529 7530 ierr = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7531 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7532 PetscFunctionReturn(0); 7533 } 7534 7535 /*@C 7536 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 7537 7538 Not collective 7539 7540 Input Parameters: 7541 + dmRow - The DM for the row fields 7542 . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 7543 . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 7544 . dmCol - The DM for the column fields 7545 . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 7546 . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 7547 . A - The matrix 7548 . point - The point in the DMs 7549 . values - The array of values 7550 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7551 7552 Level: intermediate 7553 7554 .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7555 @*/ 7556 PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7557 { 7558 DM_Plex *mesh = (DM_Plex*) dmRow->data; 7559 PetscInt *indicesRow, *indicesCol; 7560 PetscInt numIndicesRow, numIndicesCol; 7561 const PetscScalar *valuesOrig = values; 7562 PetscErrorCode ierr; 7563 7564 PetscFunctionBegin; 7565 PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 7566 if (!sectionRow) {ierr = DMGetLocalSection(dmRow, §ionRow);CHKERRQ(ierr);} 7567 PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 7568 if (!globalSectionRow) {ierr = DMGetGlobalSection(dmRow, &globalSectionRow);CHKERRQ(ierr);} 7569 PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 7570 PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 7571 if (!sectionCol) {ierr = DMGetLocalSection(dmCol, §ionCol);CHKERRQ(ierr);} 7572 PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 7573 if (!globalSectionCol) {ierr = DMGetGlobalSection(dmCol, &globalSectionCol);CHKERRQ(ierr);} 7574 PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 7575 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7576 7577 ierr = DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7578 ierr = DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7579 7580 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr);} 7581 ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 7582 if (ierr) { 7583 PetscMPIInt rank; 7584 PetscErrorCode ierr2; 7585 7586 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7587 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7588 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr2); 7589 ierr2 = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7590 ierr2 = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7591 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7592 CHKERRQ(ierr); 7593 } 7594 7595 ierr = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7596 ierr = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7597 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7598 PetscFunctionReturn(0); 7599 } 7600 7601 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7602 { 7603 DM_Plex *mesh = (DM_Plex*) dmf->data; 7604 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7605 PetscInt *cpoints = NULL; 7606 PetscInt *findices, *cindices; 7607 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7608 PetscInt foffsets[32], coffsets[32]; 7609 DMPolytopeType ct; 7610 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7611 PetscErrorCode ierr; 7612 7613 PetscFunctionBegin; 7614 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7615 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7616 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7617 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7618 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7619 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7620 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7621 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7622 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7623 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7624 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7625 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7626 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7627 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7628 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7629 /* Column indices */ 7630 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7631 maxFPoints = numCPoints; 7632 /* Compress out points not in the section */ 7633 /* TODO: Squeeze out points with 0 dof as well */ 7634 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7635 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7636 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7637 cpoints[q*2] = cpoints[p]; 7638 cpoints[q*2+1] = cpoints[p+1]; 7639 ++q; 7640 } 7641 } 7642 numCPoints = q; 7643 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7644 PetscInt fdof; 7645 7646 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7647 if (!dof) continue; 7648 for (f = 0; f < numFields; ++f) { 7649 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7650 coffsets[f+1] += fdof; 7651 } 7652 numCIndices += dof; 7653 } 7654 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7655 /* Row indices */ 7656 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7657 { 7658 DMPlexTransform tr; 7659 DMPolytopeType *rct; 7660 PetscInt *rsize, *rcone, *rornt, Nt; 7661 7662 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7663 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7664 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7665 numSubcells = rsize[Nt-1]; 7666 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7667 } 7668 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7669 for (r = 0, q = 0; r < numSubcells; ++r) { 7670 /* TODO Map from coarse to fine cells */ 7671 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7672 /* Compress out points not in the section */ 7673 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7674 for (p = 0; p < numFPoints*2; p += 2) { 7675 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7676 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7677 if (!dof) continue; 7678 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7679 if (s < q) continue; 7680 ftotpoints[q*2] = fpoints[p]; 7681 ftotpoints[q*2+1] = fpoints[p+1]; 7682 ++q; 7683 } 7684 } 7685 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7686 } 7687 numFPoints = q; 7688 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7689 PetscInt fdof; 7690 7691 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7692 if (!dof) continue; 7693 for (f = 0; f < numFields; ++f) { 7694 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7695 foffsets[f+1] += fdof; 7696 } 7697 numFIndices += dof; 7698 } 7699 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7700 7701 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7702 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7703 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7704 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7705 if (numFields) { 7706 const PetscInt **permsF[32] = {NULL}; 7707 const PetscInt **permsC[32] = {NULL}; 7708 7709 for (f = 0; f < numFields; f++) { 7710 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7711 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7712 } 7713 for (p = 0; p < numFPoints; p++) { 7714 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7715 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7716 } 7717 for (p = 0; p < numCPoints; p++) { 7718 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7719 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7720 } 7721 for (f = 0; f < numFields; f++) { 7722 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7723 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7724 } 7725 } else { 7726 const PetscInt **permsF = NULL; 7727 const PetscInt **permsC = NULL; 7728 7729 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7730 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7731 for (p = 0, off = 0; p < numFPoints; p++) { 7732 const PetscInt *perm = permsF ? permsF[p] : NULL; 7733 7734 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7735 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7736 } 7737 for (p = 0, off = 0; p < numCPoints; p++) { 7738 const PetscInt *perm = permsC ? permsC[p] : NULL; 7739 7740 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7741 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7742 } 7743 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7744 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7745 } 7746 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 7747 /* TODO: flips */ 7748 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7749 if (ierr) { 7750 PetscMPIInt rank; 7751 PetscErrorCode ierr2; 7752 7753 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7754 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7755 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 7756 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 7757 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 7758 CHKERRQ(ierr); 7759 } 7760 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7761 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7762 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7763 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7764 PetscFunctionReturn(0); 7765 } 7766 7767 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 7768 { 7769 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7770 PetscInt *cpoints = NULL; 7771 PetscInt foffsets[32], coffsets[32]; 7772 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7773 DMPolytopeType ct; 7774 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7775 PetscErrorCode ierr; 7776 7777 PetscFunctionBegin; 7778 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7779 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7780 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7781 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7782 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7783 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7784 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7785 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7786 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7787 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7788 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7789 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7790 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7791 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7792 /* Column indices */ 7793 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7794 maxFPoints = numCPoints; 7795 /* Compress out points not in the section */ 7796 /* TODO: Squeeze out points with 0 dof as well */ 7797 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7798 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7799 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7800 cpoints[q*2] = cpoints[p]; 7801 cpoints[q*2+1] = cpoints[p+1]; 7802 ++q; 7803 } 7804 } 7805 numCPoints = q; 7806 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7807 PetscInt fdof; 7808 7809 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7810 if (!dof) continue; 7811 for (f = 0; f < numFields; ++f) { 7812 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7813 coffsets[f+1] += fdof; 7814 } 7815 numCIndices += dof; 7816 } 7817 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7818 /* Row indices */ 7819 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7820 { 7821 DMPlexTransform tr; 7822 DMPolytopeType *rct; 7823 PetscInt *rsize, *rcone, *rornt, Nt; 7824 7825 ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr); 7826 ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr); 7827 ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 7828 numSubcells = rsize[Nt-1]; 7829 ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr); 7830 } 7831 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7832 for (r = 0, q = 0; r < numSubcells; ++r) { 7833 /* TODO Map from coarse to fine cells */ 7834 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7835 /* Compress out points not in the section */ 7836 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7837 for (p = 0; p < numFPoints*2; p += 2) { 7838 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7839 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7840 if (!dof) continue; 7841 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7842 if (s < q) continue; 7843 ftotpoints[q*2] = fpoints[p]; 7844 ftotpoints[q*2+1] = fpoints[p+1]; 7845 ++q; 7846 } 7847 } 7848 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7849 } 7850 numFPoints = q; 7851 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7852 PetscInt fdof; 7853 7854 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7855 if (!dof) continue; 7856 for (f = 0; f < numFields; ++f) { 7857 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7858 foffsets[f+1] += fdof; 7859 } 7860 numFIndices += dof; 7861 } 7862 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7863 7864 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7865 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7866 if (numFields) { 7867 const PetscInt **permsF[32] = {NULL}; 7868 const PetscInt **permsC[32] = {NULL}; 7869 7870 for (f = 0; f < numFields; f++) { 7871 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7872 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7873 } 7874 for (p = 0; p < numFPoints; p++) { 7875 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7876 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7877 } 7878 for (p = 0; p < numCPoints; p++) { 7879 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7880 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7881 } 7882 for (f = 0; f < numFields; f++) { 7883 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7884 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7885 } 7886 } else { 7887 const PetscInt **permsF = NULL; 7888 const PetscInt **permsC = NULL; 7889 7890 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7891 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7892 for (p = 0, off = 0; p < numFPoints; p++) { 7893 const PetscInt *perm = permsF ? permsF[p] : NULL; 7894 7895 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7896 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7897 } 7898 for (p = 0, off = 0; p < numCPoints; p++) { 7899 const PetscInt *perm = permsC ? permsC[p] : NULL; 7900 7901 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7902 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7903 } 7904 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7905 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7906 } 7907 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7908 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7909 PetscFunctionReturn(0); 7910 } 7911 7912 /*@C 7913 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 7914 7915 Input Parameter: 7916 . dm - The DMPlex object 7917 7918 Output Parameter: 7919 . cellHeight - The height of a cell 7920 7921 Level: developer 7922 7923 .seealso DMPlexSetVTKCellHeight() 7924 @*/ 7925 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7926 { 7927 DM_Plex *mesh = (DM_Plex*) dm->data; 7928 7929 PetscFunctionBegin; 7930 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7931 PetscValidPointer(cellHeight, 2); 7932 *cellHeight = mesh->vtkCellHeight; 7933 PetscFunctionReturn(0); 7934 } 7935 7936 /*@C 7937 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 7938 7939 Input Parameters: 7940 + dm - The DMPlex object 7941 - cellHeight - The height of a cell 7942 7943 Level: developer 7944 7945 .seealso DMPlexGetVTKCellHeight() 7946 @*/ 7947 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7948 { 7949 DM_Plex *mesh = (DM_Plex*) dm->data; 7950 7951 PetscFunctionBegin; 7952 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7953 mesh->vtkCellHeight = cellHeight; 7954 PetscFunctionReturn(0); 7955 } 7956 7957 /*@ 7958 DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 7959 7960 Input Parameter: 7961 . dm - The DMPlex object 7962 7963 Output Parameters: 7964 + gcStart - The first ghost cell, or NULL 7965 - gcEnd - The upper bound on ghost cells, or NULL 7966 7967 Level: advanced 7968 7969 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 7970 @*/ 7971 PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 7972 { 7973 DMLabel ctLabel; 7974 PetscErrorCode ierr; 7975 7976 PetscFunctionBegin; 7977 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7978 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 7979 ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr); 7980 PetscFunctionReturn(0); 7981 } 7982 7983 /* We can easily have a form that takes an IS instead */ 7984 PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 7985 { 7986 PetscSection section, globalSection; 7987 PetscInt *numbers, p; 7988 PetscErrorCode ierr; 7989 7990 PetscFunctionBegin; 7991 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7992 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 7993 for (p = pStart; p < pEnd; ++p) { 7994 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 7995 } 7996 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 7997 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7998 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 7999 for (p = pStart; p < pEnd; ++p) { 8000 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 8001 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 8002 else numbers[p-pStart] += shift; 8003 } 8004 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 8005 if (globalSize) { 8006 PetscLayout layout; 8007 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 8008 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 8009 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 8010 } 8011 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 8012 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8013 PetscFunctionReturn(0); 8014 } 8015 8016 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8017 { 8018 PetscInt cellHeight, cStart, cEnd; 8019 PetscErrorCode ierr; 8020 8021 PetscFunctionBegin; 8022 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8023 if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 8024 else {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 8025 ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 8026 PetscFunctionReturn(0); 8027 } 8028 8029 /*@ 8030 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 8031 8032 Input Parameter: 8033 . dm - The DMPlex object 8034 8035 Output Parameter: 8036 . globalCellNumbers - Global cell numbers for all cells on this process 8037 8038 Level: developer 8039 8040 .seealso DMPlexGetVertexNumbering() 8041 @*/ 8042 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8043 { 8044 DM_Plex *mesh = (DM_Plex*) dm->data; 8045 PetscErrorCode ierr; 8046 8047 PetscFunctionBegin; 8048 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8049 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 8050 *globalCellNumbers = mesh->globalCellNumbers; 8051 PetscFunctionReturn(0); 8052 } 8053 8054 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8055 { 8056 PetscInt vStart, vEnd; 8057 PetscErrorCode ierr; 8058 8059 PetscFunctionBegin; 8060 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8061 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8062 ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 8063 PetscFunctionReturn(0); 8064 } 8065 8066 /*@ 8067 DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 8068 8069 Input Parameter: 8070 . dm - The DMPlex object 8071 8072 Output Parameter: 8073 . globalVertexNumbers - Global vertex numbers for all vertices on this process 8074 8075 Level: developer 8076 8077 .seealso DMPlexGetCellNumbering() 8078 @*/ 8079 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8080 { 8081 DM_Plex *mesh = (DM_Plex*) dm->data; 8082 PetscErrorCode ierr; 8083 8084 PetscFunctionBegin; 8085 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8086 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 8087 *globalVertexNumbers = mesh->globalVertexNumbers; 8088 PetscFunctionReturn(0); 8089 } 8090 8091 /*@ 8092 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 8093 8094 Input Parameter: 8095 . dm - The DMPlex object 8096 8097 Output Parameter: 8098 . globalPointNumbers - Global numbers for all points on this process 8099 8100 Level: developer 8101 8102 .seealso DMPlexGetCellNumbering() 8103 @*/ 8104 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8105 { 8106 IS nums[4]; 8107 PetscInt depths[4], gdepths[4], starts[4]; 8108 PetscInt depth, d, shift = 0; 8109 PetscErrorCode ierr; 8110 8111 PetscFunctionBegin; 8112 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8113 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8114 /* For unstratified meshes use dim instead of depth */ 8115 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 8116 for (d = 0; d <= depth; ++d) { 8117 PetscInt end; 8118 8119 depths[d] = depth-d; 8120 ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 8121 if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 8122 } 8123 ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 8124 ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 8125 for (d = 0; d <= depth; ++d) { 8126 if (starts[d] >= 0 && depths[d] != gdepths[d]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 8127 } 8128 for (d = 0; d <= depth; ++d) { 8129 PetscInt pStart, pEnd, gsize; 8130 8131 ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 8132 ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 8133 shift += gsize; 8134 } 8135 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 8136 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 8137 PetscFunctionReturn(0); 8138 } 8139 8140 /*@ 8141 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 8142 8143 Input Parameter: 8144 . dm - The DMPlex object 8145 8146 Output Parameter: 8147 . ranks - The rank field 8148 8149 Options Database Keys: 8150 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 8151 8152 Level: intermediate 8153 8154 .seealso: DMView() 8155 @*/ 8156 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8157 { 8158 DM rdm; 8159 PetscFE fe; 8160 PetscScalar *r; 8161 PetscMPIInt rank; 8162 DMPolytopeType ct; 8163 PetscInt dim, cStart, cEnd, c; 8164 PetscBool simplex; 8165 PetscErrorCode ierr; 8166 8167 PetscFunctionBeginUser; 8168 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8169 PetscValidPointer(ranks, 2); 8170 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 8171 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8172 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8173 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8174 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 8175 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 8176 ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 8177 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 8178 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8179 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8180 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8181 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 8182 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 8183 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 8184 for (c = cStart; c < cEnd; ++c) { 8185 PetscScalar *lr; 8186 8187 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 8188 if (lr) *lr = rank; 8189 } 8190 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 8191 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8192 PetscFunctionReturn(0); 8193 } 8194 8195 /*@ 8196 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 8197 8198 Input Parameters: 8199 + dm - The DMPlex 8200 - label - The DMLabel 8201 8202 Output Parameter: 8203 . val - The label value field 8204 8205 Options Database Keys: 8206 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 8207 8208 Level: intermediate 8209 8210 .seealso: DMView() 8211 @*/ 8212 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8213 { 8214 DM rdm; 8215 PetscFE fe; 8216 PetscScalar *v; 8217 PetscInt dim, cStart, cEnd, c; 8218 PetscErrorCode ierr; 8219 8220 PetscFunctionBeginUser; 8221 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8222 PetscValidPointer(label, 2); 8223 PetscValidPointer(val, 3); 8224 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8225 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8226 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 8227 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 8228 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8229 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8230 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8231 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8232 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 8233 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 8234 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 8235 for (c = cStart; c < cEnd; ++c) { 8236 PetscScalar *lv; 8237 PetscInt cval; 8238 8239 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 8240 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 8241 *lv = cval; 8242 } 8243 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 8244 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8245 PetscFunctionReturn(0); 8246 } 8247 8248 /*@ 8249 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8250 8251 Input Parameter: 8252 . dm - The DMPlex object 8253 8254 Notes: 8255 This is a useful diagnostic when creating meshes programmatically. 8256 8257 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8258 8259 Level: developer 8260 8261 .seealso: DMCreate(), DMSetFromOptions() 8262 @*/ 8263 PetscErrorCode DMPlexCheckSymmetry(DM dm) 8264 { 8265 PetscSection coneSection, supportSection; 8266 const PetscInt *cone, *support; 8267 PetscInt coneSize, c, supportSize, s; 8268 PetscInt pStart, pEnd, p, pp, csize, ssize; 8269 PetscBool storagecheck = PETSC_TRUE; 8270 PetscErrorCode ierr; 8271 8272 PetscFunctionBegin; 8273 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8274 ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr); 8275 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 8276 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 8277 /* Check that point p is found in the support of its cone points, and vice versa */ 8278 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8279 for (p = pStart; p < pEnd; ++p) { 8280 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8281 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8282 for (c = 0; c < coneSize; ++c) { 8283 PetscBool dup = PETSC_FALSE; 8284 PetscInt d; 8285 for (d = c-1; d >= 0; --d) { 8286 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 8287 } 8288 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 8289 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 8290 for (s = 0; s < supportSize; ++s) { 8291 if (support[s] == p) break; 8292 } 8293 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 8294 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 8295 for (s = 0; s < coneSize; ++s) { 8296 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 8297 } 8298 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8299 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 8300 for (s = 0; s < supportSize; ++s) { 8301 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 8302 } 8303 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8304 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 8305 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 8306 } 8307 } 8308 ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 8309 if (p != pp) { storagecheck = PETSC_FALSE; continue; } 8310 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 8311 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 8312 for (s = 0; s < supportSize; ++s) { 8313 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 8314 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 8315 for (c = 0; c < coneSize; ++c) { 8316 ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 8317 if (cone[c] != pp) { c = 0; break; } 8318 if (cone[c] == p) break; 8319 } 8320 if (c >= coneSize) { 8321 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 8322 for (c = 0; c < supportSize; ++c) { 8323 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 8324 } 8325 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8326 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 8327 for (c = 0; c < coneSize; ++c) { 8328 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 8329 } 8330 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8331 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 8332 } 8333 } 8334 } 8335 if (storagecheck) { 8336 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 8337 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 8338 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 8339 } 8340 PetscFunctionReturn(0); 8341 } 8342 8343 /* 8344 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. 8345 */ 8346 static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8347 { 8348 DMPolytopeType cct; 8349 PetscInt ptpoints[4]; 8350 const PetscInt *cone, *ccone, *ptcone; 8351 PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8352 PetscErrorCode ierr; 8353 8354 PetscFunctionBegin; 8355 *unsplit = 0; 8356 switch (ct) { 8357 case DM_POLYTOPE_POINT_PRISM_TENSOR: 8358 ptpoints[npt++] = c; 8359 break; 8360 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8361 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8362 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8363 for (cp = 0; cp < coneSize; ++cp) { 8364 ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr); 8365 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8366 } 8367 break; 8368 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8369 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8370 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8371 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8372 for (cp = 0; cp < coneSize; ++cp) { 8373 ierr = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr); 8374 ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr); 8375 for (ccp = 0; ccp < cconeSize; ++ccp) { 8376 ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr); 8377 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8378 PetscInt p; 8379 for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8380 if (p == npt) ptpoints[npt++] = ccone[ccp]; 8381 } 8382 } 8383 } 8384 break; 8385 default: break; 8386 } 8387 for (pt = 0; pt < npt; ++pt) { 8388 ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr); 8389 if (ptcone[0] == ptcone[1]) ++(*unsplit); 8390 } 8391 PetscFunctionReturn(0); 8392 } 8393 8394 /*@ 8395 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8396 8397 Input Parameters: 8398 + dm - The DMPlex object 8399 - cellHeight - Normally 0 8400 8401 Notes: 8402 This is a useful diagnostic when creating meshes programmatically. 8403 Currently applicable only to homogeneous simplex or tensor meshes. 8404 8405 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8406 8407 Level: developer 8408 8409 .seealso: DMCreate(), DMSetFromOptions() 8410 @*/ 8411 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8412 { 8413 DMPlexInterpolatedFlag interp; 8414 DMPolytopeType ct; 8415 PetscInt vStart, vEnd, cStart, cEnd, c; 8416 PetscErrorCode ierr; 8417 8418 PetscFunctionBegin; 8419 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8420 ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr); 8421 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8422 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8423 for (c = cStart; c < cEnd; ++c) { 8424 PetscInt *closure = NULL; 8425 PetscInt coneSize, closureSize, cl, Nv = 0; 8426 8427 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8428 if ((PetscInt) ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c); 8429 if (ct == DM_POLYTOPE_UNKNOWN) continue; 8430 if (interp == DMPLEX_INTERPOLATED_FULL) { 8431 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8432 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)); 8433 } 8434 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8435 for (cl = 0; cl < closureSize*2; cl += 2) { 8436 const PetscInt p = closure[cl]; 8437 if ((p >= vStart) && (p < vEnd)) ++Nv; 8438 } 8439 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8440 /* Special Case: Tensor faces with identified vertices */ 8441 if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8442 PetscInt unsplit; 8443 8444 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8445 if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 8446 } 8447 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)); 8448 } 8449 PetscFunctionReturn(0); 8450 } 8451 8452 /*@ 8453 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 8454 8455 Not Collective 8456 8457 Input Parameters: 8458 + dm - The DMPlex object 8459 - cellHeight - Normally 0 8460 8461 Notes: 8462 This is a useful diagnostic when creating meshes programmatically. 8463 This routine is only relevant for meshes that are fully interpolated across all ranks. 8464 It will error out if a partially interpolated mesh is given on some rank. 8465 It will do nothing for locally uninterpolated mesh (as there is nothing to check). 8466 8467 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8468 8469 Level: developer 8470 8471 .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 8472 @*/ 8473 PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 8474 { 8475 PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8476 PetscErrorCode ierr; 8477 DMPlexInterpolatedFlag interpEnum; 8478 8479 PetscFunctionBegin; 8480 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8481 ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr); 8482 if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 8483 if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 8484 PetscMPIInt rank; 8485 MPI_Comm comm; 8486 8487 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8488 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8489 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 8490 } 8491 8492 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8493 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8494 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8495 for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 8496 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 8497 for (c = cStart; c < cEnd; ++c) { 8498 const PetscInt *cone, *ornt, *faceSizes, *faces; 8499 const DMPolytopeType *faceTypes; 8500 DMPolytopeType ct; 8501 PetscInt numFaces, coneSize, f; 8502 PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 8503 8504 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8505 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8506 if (unsplit) continue; 8507 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8508 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8509 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 8510 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8511 for (cl = 0; cl < closureSize*2; cl += 2) { 8512 const PetscInt p = closure[cl]; 8513 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 8514 } 8515 ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8516 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); 8517 for (f = 0; f < numFaces; ++f) { 8518 DMPolytopeType fct; 8519 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 8520 8521 ierr = DMPlexGetCellType(dm, cone[f], &fct);CHKERRQ(ierr); 8522 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8523 for (cl = 0; cl < fclosureSize*2; cl += 2) { 8524 const PetscInt p = fclosure[cl]; 8525 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 8526 } 8527 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]); 8528 for (v = 0; v < fnumCorners; ++v) { 8529 if (fclosure[v] != faces[fOff+v]) { 8530 PetscInt v1; 8531 8532 ierr = PetscPrintf(PETSC_COMM_SELF, "face closure:");CHKERRQ(ierr); 8533 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", fclosure[v1]);CHKERRQ(ierr);} 8534 ierr = PetscPrintf(PETSC_COMM_SELF, "\ncell face:");CHKERRQ(ierr); 8535 for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", faces[fOff+v1]);CHKERRQ(ierr);} 8536 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8537 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]); 8538 } 8539 } 8540 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8541 fOff += faceSizes[f]; 8542 } 8543 ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8544 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8545 } 8546 } 8547 PetscFunctionReturn(0); 8548 } 8549 8550 /*@ 8551 DMPlexCheckGeometry - Check the geometry of mesh cells 8552 8553 Input Parameter: 8554 . dm - The DMPlex object 8555 8556 Notes: 8557 This is a useful diagnostic when creating meshes programmatically. 8558 8559 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8560 8561 Level: developer 8562 8563 .seealso: DMCreate(), DMSetFromOptions() 8564 @*/ 8565 PetscErrorCode DMPlexCheckGeometry(DM dm) 8566 { 8567 Vec coordinates; 8568 PetscReal detJ, J[9], refVol = 1.0; 8569 PetscReal vol; 8570 PetscBool periodic; 8571 PetscInt dim, depth, dE, d, cStart, cEnd, c; 8572 PetscErrorCode ierr; 8573 8574 PetscFunctionBegin; 8575 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8576 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 8577 if (dim != dE) PetscFunctionReturn(0); 8578 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8579 ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr); 8580 for (d = 0; d < dim; ++d) refVol *= 2.0; 8581 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8582 /* Make sure local coordinates are created, because that step is collective */ 8583 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8584 for (c = cStart; c < cEnd; ++c) { 8585 DMPolytopeType ct; 8586 PetscInt unsplit; 8587 PetscBool ignoreZeroVol = PETSC_FALSE; 8588 8589 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8590 switch (ct) { 8591 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8592 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8593 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8594 ignoreZeroVol = PETSC_TRUE; break; 8595 default: break; 8596 } 8597 switch (ct) { 8598 case DM_POLYTOPE_TRI_PRISM: 8599 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8600 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8601 case DM_POLYTOPE_PYRAMID: 8602 continue; 8603 default: break; 8604 } 8605 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8606 if (unsplit) continue; 8607 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 8608 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); 8609 ierr = PetscInfo2(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 8610 if (depth > 1 && !periodic) { 8611 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 8612 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); 8613 ierr = PetscInfo2(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 8614 } 8615 } 8616 PetscFunctionReturn(0); 8617 } 8618 8619 /*@ 8620 DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 8621 8622 Input Parameters: 8623 . dm - The DMPlex object 8624 8625 Notes: 8626 This is mainly intended for debugging/testing purposes. 8627 It currently checks only meshes with no partition overlapping. 8628 8629 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8630 8631 Level: developer 8632 8633 .seealso: DMGetPointSF(), DMSetFromOptions() 8634 @*/ 8635 PetscErrorCode DMPlexCheckPointSF(DM dm) 8636 { 8637 PetscSF pointSF; 8638 PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 8639 const PetscInt *locals, *rootdegree; 8640 PetscBool distributed; 8641 PetscErrorCode ierr; 8642 8643 PetscFunctionBegin; 8644 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8645 ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr); 8646 ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 8647 if (!distributed) PetscFunctionReturn(0); 8648 ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 8649 if (overlap) { 8650 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping");CHKERRQ(ierr); 8651 PetscFunctionReturn(0); 8652 } 8653 if (!pointSF) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 8654 ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr); 8655 if (nroots < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 8656 ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 8657 ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 8658 8659 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 8660 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8661 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8662 for (l = 0; l < nleaves; ++l) { 8663 const PetscInt point = locals[l]; 8664 8665 if (point >= cStart && point < cEnd) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 8666 } 8667 8668 /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 8669 for (l = 0; l < nleaves; ++l) { 8670 const PetscInt point = locals[l]; 8671 const PetscInt *cone; 8672 PetscInt coneSize, c, idx; 8673 8674 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 8675 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 8676 for (c = 0; c < coneSize; ++c) { 8677 if (!rootdegree[cone[c]]) { 8678 ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr); 8679 if (idx < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 8680 } 8681 } 8682 } 8683 PetscFunctionReturn(0); 8684 } 8685 8686 PetscErrorCode DMPlexCheckAll_Internal(DM dm, PetscInt cellHeight) 8687 { 8688 PetscErrorCode ierr; 8689 8690 PetscFunctionBegin; 8691 ierr = DMPlexCheckSymmetry(dm);CHKERRQ(ierr); 8692 ierr = DMPlexCheckSkeleton(dm, cellHeight);CHKERRQ(ierr); 8693 ierr = DMPlexCheckFaces(dm, cellHeight);CHKERRQ(ierr); 8694 ierr = DMPlexCheckGeometry(dm);CHKERRQ(ierr); 8695 ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr); 8696 ierr = DMPlexCheckInterfaceCones(dm);CHKERRQ(ierr); 8697 PetscFunctionReturn(0); 8698 } 8699 8700 typedef struct cell_stats 8701 { 8702 PetscReal min, max, sum, squaresum; 8703 PetscInt count; 8704 } cell_stats_t; 8705 8706 static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8707 { 8708 PetscInt i, N = *len; 8709 8710 for (i = 0; i < N; i++) { 8711 cell_stats_t *A = (cell_stats_t *) a; 8712 cell_stats_t *B = (cell_stats_t *) b; 8713 8714 B->min = PetscMin(A->min,B->min); 8715 B->max = PetscMax(A->max,B->max); 8716 B->sum += A->sum; 8717 B->squaresum += A->squaresum; 8718 B->count += A->count; 8719 } 8720 } 8721 8722 /*@ 8723 DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8724 8725 Collective on dm 8726 8727 Input Parameters: 8728 + dm - The DMPlex object 8729 . output - If true, statistics will be displayed on stdout 8730 - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8731 8732 Notes: 8733 This is mainly intended for debugging/testing purposes. 8734 8735 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8736 8737 Level: developer 8738 8739 .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality() 8740 @*/ 8741 PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8742 { 8743 DM dmCoarse; 8744 cell_stats_t stats, globalStats; 8745 MPI_Comm comm = PetscObjectComm((PetscObject)dm); 8746 PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 8747 PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8748 PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 8749 PetscMPIInt rank,size; 8750 PetscErrorCode ierr; 8751 8752 PetscFunctionBegin; 8753 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8754 stats.min = PETSC_MAX_REAL; 8755 stats.max = PETSC_MIN_REAL; 8756 stats.sum = stats.squaresum = 0.; 8757 stats.count = 0; 8758 8759 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 8760 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8761 ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr); 8762 ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr); 8763 ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 8764 ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); 8765 for (c = cStart; c < cEnd; c++) { 8766 PetscInt i; 8767 PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8768 8769 ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 8770 if (detJ < 0.0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 8771 for (i = 0; i < PetscSqr(cdim); ++i) { 8772 frobJ += J[i] * J[i]; 8773 frobInvJ += invJ[i] * invJ[i]; 8774 } 8775 cond2 = frobJ * frobInvJ; 8776 cond = PetscSqrtReal(cond2); 8777 8778 stats.min = PetscMin(stats.min,cond); 8779 stats.max = PetscMax(stats.max,cond); 8780 stats.sum += cond; 8781 stats.squaresum += cond2; 8782 stats.count++; 8783 if (output && cond > limit) { 8784 PetscSection coordSection; 8785 Vec coordsLocal; 8786 PetscScalar *coords = NULL; 8787 PetscInt Nv, d, clSize, cl, *closure = NULL; 8788 8789 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8790 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8791 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8792 ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr); 8793 for (i = 0; i < Nv/cdim; ++i) { 8794 ierr = PetscSynchronizedPrintf(comm, " Vertex %D: (", i);CHKERRQ(ierr); 8795 for (d = 0; d < cdim; ++d) { 8796 if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);} 8797 ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr); 8798 } 8799 ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr); 8800 } 8801 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8802 for (cl = 0; cl < clSize*2; cl += 2) { 8803 const PetscInt edge = closure[cl]; 8804 8805 if ((edge >= eStart) && (edge < eEnd)) { 8806 PetscReal len; 8807 8808 ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr); 8809 ierr = PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr); 8810 } 8811 } 8812 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8813 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8814 } 8815 } 8816 if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 8817 8818 if (size > 1) { 8819 PetscMPIInt blockLengths[2] = {4,1}; 8820 MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8821 MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8822 MPI_Op statReduce; 8823 8824 ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRMPI(ierr); 8825 ierr = MPI_Type_commit(&statType);CHKERRMPI(ierr); 8826 ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRMPI(ierr); 8827 ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRMPI(ierr); 8828 ierr = MPI_Op_free(&statReduce);CHKERRMPI(ierr); 8829 ierr = MPI_Type_free(&statType);CHKERRMPI(ierr); 8830 } else { 8831 ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr); 8832 } 8833 if (rank == 0) { 8834 count = globalStats.count; 8835 min = globalStats.min; 8836 max = globalStats.max; 8837 mean = globalStats.sum / globalStats.count; 8838 stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8839 } 8840 8841 if (output) { 8842 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); 8843 } 8844 ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 8845 8846 ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 8847 if (dmCoarse) { 8848 PetscBool isplex; 8849 8850 ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 8851 if (isplex) { 8852 ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr); 8853 } 8854 } 8855 PetscFunctionReturn(0); 8856 } 8857 8858 /*@ 8859 DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8860 orthogonal quality below given tolerance. 8861 8862 Collective on dm 8863 8864 Input Parameters: 8865 + dm - The DMPlex object 8866 . fv - Optional PetscFV object for pre-computed cell/face centroid information 8867 - atol - [0, 1] Absolute tolerance for tagging cells. 8868 8869 Output Parameters: 8870 + OrthQual - Vec containing orthogonal quality per cell 8871 - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8872 8873 Options Database Keys: 8874 + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8875 supported. 8876 - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8877 8878 Notes: 8879 Orthogonal quality is given by the following formula: 8880 8881 \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8882 8883 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 8884 is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8885 current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8886 calculating the cosine of the angle between these vectors. 8887 8888 Orthogonal quality ranges from 1 (best) to 0 (worst). 8889 8890 This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8891 pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8892 8893 Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8894 8895 Level: intermediate 8896 8897 .seealso: DMPlexCheckCellShape(), DMCreateLabel() 8898 @*/ 8899 PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8900 { 8901 PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 8902 PetscInt *idx; 8903 PetscScalar *oqVals; 8904 const PetscScalar *cellGeomArr, *faceGeomArr; 8905 PetscReal *ci, *fi, *Ai; 8906 MPI_Comm comm; 8907 Vec cellgeom, facegeom; 8908 DM dmFace, dmCell; 8909 IS glob; 8910 ISLocalToGlobalMapping ltog; 8911 PetscViewer vwr; 8912 PetscErrorCode ierr; 8913 8914 PetscFunctionBegin; 8915 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8916 if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8917 PetscValidPointer(OrthQual, 4); 8918 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); 8919 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8920 ierr = DMGetDimension(dm, &nc);CHKERRQ(ierr); 8921 if (nc < 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc); 8922 { 8923 DMPlexInterpolatedFlag interpFlag; 8924 8925 ierr = DMPlexIsInterpolated(dm, &interpFlag);CHKERRQ(ierr); 8926 if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 8927 PetscMPIInt rank; 8928 8929 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8930 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 8931 } 8932 } 8933 if (OrthQualLabel) { 8934 PetscValidPointer(OrthQualLabel, 5); 8935 ierr = DMCreateLabel(dm, "Orthogonal_Quality");CHKERRQ(ierr); 8936 ierr = DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel);CHKERRQ(ierr); 8937 } else {*OrthQualLabel = NULL;} 8938 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8939 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8940 ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob);CHKERRQ(ierr); 8941 ierr = ISLocalToGlobalMappingCreateIS(glob, <og);CHKERRQ(ierr); 8942 ierr = ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 8943 ierr = VecCreate(comm, OrthQual);CHKERRQ(ierr); 8944 ierr = VecSetType(*OrthQual, VECSTANDARD);CHKERRQ(ierr); 8945 ierr = VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr); 8946 ierr = VecSetLocalToGlobalMapping(*OrthQual, ltog);CHKERRQ(ierr); 8947 ierr = VecSetUp(*OrthQual);CHKERRQ(ierr); 8948 ierr = ISDestroy(&glob);CHKERRQ(ierr); 8949 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 8950 ierr = DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL);CHKERRQ(ierr); 8951 ierr = VecGetArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8952 ierr = VecGetArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8953 ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr); 8954 ierr = VecGetDM(facegeom, &dmFace);CHKERRQ(ierr); 8955 ierr = PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai);CHKERRQ(ierr); 8956 for (cell = cStart; cell < cEnd; cellIter++,cell++) { 8957 PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 8958 PetscInt cellarr[2], *adj = NULL; 8959 PetscScalar *cArr, *fArr; 8960 PetscReal minvalc = 1.0, minvalf = 1.0; 8961 PetscFVCellGeom *cg; 8962 8963 idx[cellIter] = cell-cStart; 8964 cellarr[0] = cell; 8965 /* Make indexing into cellGeom easier */ 8966 ierr = DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg);CHKERRQ(ierr); 8967 ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj);CHKERRQ(ierr); 8968 /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 8969 ierr = PetscCalloc2(adjSize, &cArr, adjSize, &fArr);CHKERRQ(ierr); 8970 for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 8971 PetscInt i; 8972 const PetscInt neigh = adj[cellneigh]; 8973 PetscReal normci = 0, normfi = 0, normai = 0; 8974 PetscFVCellGeom *cgneigh; 8975 PetscFVFaceGeom *fg; 8976 8977 /* Don't count ourselves in the neighbor list */ 8978 if (neigh == cell) continue; 8979 ierr = DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh);CHKERRQ(ierr); 8980 cellarr[1] = neigh; 8981 { 8982 PetscInt numcovpts; 8983 const PetscInt *covpts; 8984 8985 ierr = DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 8986 ierr = DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg);CHKERRQ(ierr); 8987 ierr = DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 8988 } 8989 8990 /* Compute c_i, f_i and their norms */ 8991 for (i = 0; i < nc; i++) { 8992 ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 8993 fi[i] = fg->centroid[i] - cg->centroid[i]; 8994 Ai[i] = fg->normal[i]; 8995 normci += PetscPowReal(ci[i], 2); 8996 normfi += PetscPowReal(fi[i], 2); 8997 normai += PetscPowReal(Ai[i], 2); 8998 } 8999 normci = PetscSqrtReal(normci); 9000 normfi = PetscSqrtReal(normfi); 9001 normai = PetscSqrtReal(normai); 9002 9003 /* Normalize and compute for each face-cell-normal pair */ 9004 for (i = 0; i < nc; i++) { 9005 ci[i] = ci[i]/normci; 9006 fi[i] = fi[i]/normfi; 9007 Ai[i] = Ai[i]/normai; 9008 /* PetscAbs because I don't know if normals are guaranteed to point out */ 9009 cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 9010 fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 9011 } 9012 if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 9013 minvalc = PetscRealPart(cArr[cellneighiter]); 9014 } 9015 if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 9016 minvalf = PetscRealPart(fArr[cellneighiter]); 9017 } 9018 } 9019 ierr = PetscFree(adj);CHKERRQ(ierr); 9020 ierr = PetscFree2(cArr, fArr);CHKERRQ(ierr); 9021 /* Defer to cell if they're equal */ 9022 oqVals[cellIter] = PetscMin(minvalf, minvalc); 9023 if (OrthQualLabel) { 9024 if (PetscRealPart(oqVals[cellIter]) <= atol) {ierr = DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE);CHKERRQ(ierr);} 9025 } 9026 } 9027 ierr = VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES);CHKERRQ(ierr); 9028 ierr = VecAssemblyBegin(*OrthQual);CHKERRQ(ierr); 9029 ierr = VecAssemblyEnd(*OrthQual);CHKERRQ(ierr); 9030 ierr = VecRestoreArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 9031 ierr = VecRestoreArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 9032 ierr = PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL);CHKERRQ(ierr); 9033 if (OrthQualLabel) { 9034 if (vwr) {ierr = DMLabelView(*OrthQualLabel, vwr);CHKERRQ(ierr);} 9035 } 9036 ierr = PetscFree5(idx, oqVals, ci, fi, Ai);CHKERRQ(ierr); 9037 ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr); 9038 ierr = VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view");CHKERRQ(ierr); 9039 PetscFunctionReturn(0); 9040 } 9041 9042 /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 9043 * interpolator construction */ 9044 static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9045 { 9046 PetscSection section, newSection, gsection; 9047 PetscSF sf; 9048 PetscBool hasConstraints, ghasConstraints; 9049 PetscErrorCode ierr; 9050 9051 PetscFunctionBegin; 9052 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9053 PetscValidPointer(odm,2); 9054 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9055 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 9056 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 9057 if (!ghasConstraints) { 9058 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 9059 *odm = dm; 9060 PetscFunctionReturn(0); 9061 } 9062 ierr = DMClone(dm, odm);CHKERRQ(ierr); 9063 ierr = DMCopyFields(dm, *odm);CHKERRQ(ierr); 9064 ierr = DMGetLocalSection(*odm, &newSection);CHKERRQ(ierr); 9065 ierr = DMGetPointSF(*odm, &sf);CHKERRQ(ierr); 9066 ierr = PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 9067 ierr = DMSetGlobalSection(*odm, gsection);CHKERRQ(ierr); 9068 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 9069 PetscFunctionReturn(0); 9070 } 9071 9072 static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9073 { 9074 DM dmco, dmfo; 9075 Mat interpo; 9076 Vec rscale; 9077 Vec cglobalo, clocal; 9078 Vec fglobal, fglobalo, flocal; 9079 PetscBool regular; 9080 PetscErrorCode ierr; 9081 9082 PetscFunctionBegin; 9083 ierr = DMGetFullDM(dmc, &dmco);CHKERRQ(ierr); 9084 ierr = DMGetFullDM(dmf, &dmfo);CHKERRQ(ierr); 9085 ierr = DMSetCoarseDM(dmfo, dmco);CHKERRQ(ierr); 9086 ierr = DMPlexGetRegularRefinement(dmf, ®ular);CHKERRQ(ierr); 9087 ierr = DMPlexSetRegularRefinement(dmfo, regular);CHKERRQ(ierr); 9088 ierr = DMCreateInterpolation(dmco, dmfo, &interpo, &rscale);CHKERRQ(ierr); 9089 ierr = DMCreateGlobalVector(dmco, &cglobalo);CHKERRQ(ierr); 9090 ierr = DMCreateLocalVector(dmc, &clocal);CHKERRQ(ierr); 9091 ierr = VecSet(cglobalo, 0.);CHKERRQ(ierr); 9092 ierr = VecSet(clocal, 0.);CHKERRQ(ierr); 9093 ierr = DMCreateGlobalVector(dmf, &fglobal);CHKERRQ(ierr); 9094 ierr = DMCreateGlobalVector(dmfo, &fglobalo);CHKERRQ(ierr); 9095 ierr = DMCreateLocalVector(dmf, &flocal);CHKERRQ(ierr); 9096 ierr = VecSet(fglobal, 0.);CHKERRQ(ierr); 9097 ierr = VecSet(fglobalo, 0.);CHKERRQ(ierr); 9098 ierr = VecSet(flocal, 0.);CHKERRQ(ierr); 9099 ierr = DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL);CHKERRQ(ierr); 9100 ierr = DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9101 ierr = DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 9102 ierr = MatMult(interpo, cglobalo, fglobalo);CHKERRQ(ierr); 9103 ierr = DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9104 ierr = DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 9105 ierr = DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9106 ierr = DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 9107 *shift = fglobal; 9108 ierr = VecDestroy(&flocal);CHKERRQ(ierr); 9109 ierr = VecDestroy(&fglobalo);CHKERRQ(ierr); 9110 ierr = VecDestroy(&clocal);CHKERRQ(ierr); 9111 ierr = VecDestroy(&cglobalo);CHKERRQ(ierr); 9112 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9113 ierr = MatDestroy(&interpo);CHKERRQ(ierr); 9114 ierr = DMDestroy(&dmfo);CHKERRQ(ierr); 9115 ierr = DMDestroy(&dmco);CHKERRQ(ierr); 9116 PetscFunctionReturn(0); 9117 } 9118 9119 PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9120 { 9121 PetscObject shifto; 9122 Vec shift; 9123 9124 PetscErrorCode ierr; 9125 9126 PetscFunctionBegin; 9127 if (!interp) { 9128 Vec rscale; 9129 9130 ierr = DMCreateInterpolation(coarse, fine, &interp, &rscale);CHKERRQ(ierr); 9131 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 9132 } else { 9133 ierr = PetscObjectReference((PetscObject)interp);CHKERRQ(ierr); 9134 } 9135 ierr = PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto);CHKERRQ(ierr); 9136 if (!shifto) { 9137 ierr = DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift);CHKERRQ(ierr); 9138 ierr = PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift);CHKERRQ(ierr); 9139 shifto = (PetscObject) shift; 9140 ierr = VecDestroy(&shift);CHKERRQ(ierr); 9141 } 9142 shift = (Vec) shifto; 9143 ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr); 9144 ierr = VecAXPY(fineSol, 1.0, shift);CHKERRQ(ierr); 9145 ierr = MatDestroy(&interp);CHKERRQ(ierr); 9146 PetscFunctionReturn(0); 9147 } 9148 9149 /* Pointwise interpolation 9150 Just code FEM for now 9151 u^f = I u^c 9152 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 9153 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 9154 I_{ij} = psi^f_i phi^c_j 9155 */ 9156 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9157 { 9158 PetscSection gsc, gsf; 9159 PetscInt m, n; 9160 void *ctx; 9161 DM cdm; 9162 PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9163 PetscErrorCode ierr; 9164 9165 PetscFunctionBegin; 9166 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9167 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9168 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9169 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9170 9171 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 9172 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 9173 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9174 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 9175 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9176 9177 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9178 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9179 if (!isRefined || (regular && cdm == dmCoarse)) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx);CHKERRQ(ierr);} 9180 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 9181 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 9182 if (scaling) { 9183 /* Use naive scaling */ 9184 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 9185 } 9186 PetscFunctionReturn(0); 9187 } 9188 9189 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9190 { 9191 PetscErrorCode ierr; 9192 VecScatter ctx; 9193 9194 PetscFunctionBegin; 9195 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 9196 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 9197 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 9198 PetscFunctionReturn(0); 9199 } 9200 9201 static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9202 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9203 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9204 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 9205 { 9206 g0[0] = 1.0; 9207 } 9208 9209 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9210 { 9211 PetscSection gsc, gsf; 9212 PetscInt m, n; 9213 void *ctx; 9214 DM cdm; 9215 PetscBool regular; 9216 PetscErrorCode ierr; 9217 9218 PetscFunctionBegin; 9219 if (dmFine == dmCoarse) { 9220 DM dmc; 9221 PetscDS ds; 9222 Vec u; 9223 IS cellIS; 9224 PetscFormKey key; 9225 PetscInt depth; 9226 9227 ierr = DMClone(dmFine, &dmc);CHKERRQ(ierr); 9228 ierr = DMCopyDisc(dmFine, dmc);CHKERRQ(ierr); 9229 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9230 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9231 ierr = DMCreateMatrix(dmc, mass);CHKERRQ(ierr); 9232 ierr = DMGetGlobalVector(dmc, &u);CHKERRQ(ierr); 9233 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9234 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9235 ierr = MatZeroEntries(*mass);CHKERRQ(ierr); 9236 key.label = NULL; 9237 key.value = 0; 9238 key.field = 0; 9239 key.part = 0; 9240 ierr = DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL);CHKERRQ(ierr); 9241 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9242 ierr = DMRestoreGlobalVector(dmc, &u);CHKERRQ(ierr); 9243 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9244 } else { 9245 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9246 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9247 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9248 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9249 9250 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 9251 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9252 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 9253 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9254 9255 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9256 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9257 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9258 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9259 } 9260 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 9261 PetscFunctionReturn(0); 9262 } 9263 9264 /*@ 9265 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9266 9267 Input Parameter: 9268 . dm - The DMPlex object 9269 9270 Output Parameter: 9271 . regular - The flag 9272 9273 Level: intermediate 9274 9275 .seealso: DMPlexSetRegularRefinement() 9276 @*/ 9277 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 9278 { 9279 PetscFunctionBegin; 9280 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9281 PetscValidPointer(regular, 2); 9282 *regular = ((DM_Plex *) dm->data)->regularRefinement; 9283 PetscFunctionReturn(0); 9284 } 9285 9286 /*@ 9287 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9288 9289 Input Parameters: 9290 + dm - The DMPlex object 9291 - regular - The flag 9292 9293 Level: intermediate 9294 9295 .seealso: DMPlexGetRegularRefinement() 9296 @*/ 9297 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 9298 { 9299 PetscFunctionBegin; 9300 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9301 ((DM_Plex *) dm->data)->regularRefinement = regular; 9302 PetscFunctionReturn(0); 9303 } 9304 9305 /* anchors */ 9306 /*@ 9307 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9308 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 9309 9310 not collective 9311 9312 Input Parameter: 9313 . dm - The DMPlex object 9314 9315 Output Parameters: 9316 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9317 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9318 9319 Level: intermediate 9320 9321 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 9322 @*/ 9323 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9324 { 9325 DM_Plex *plex = (DM_Plex *)dm->data; 9326 PetscErrorCode ierr; 9327 9328 PetscFunctionBegin; 9329 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9330 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 9331 if (anchorSection) *anchorSection = plex->anchorSection; 9332 if (anchorIS) *anchorIS = plex->anchorIS; 9333 PetscFunctionReturn(0); 9334 } 9335 9336 /*@ 9337 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9338 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9339 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9340 9341 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9342 DMGetConstraints() and filling in the entries in the constraint matrix. 9343 9344 collective on dm 9345 9346 Input Parameters: 9347 + dm - The DMPlex object 9348 . 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). 9349 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9350 9351 The reference counts of anchorSection and anchorIS are incremented. 9352 9353 Level: intermediate 9354 9355 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 9356 @*/ 9357 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9358 { 9359 DM_Plex *plex = (DM_Plex *)dm->data; 9360 PetscMPIInt result; 9361 PetscErrorCode ierr; 9362 9363 PetscFunctionBegin; 9364 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9365 if (anchorSection) { 9366 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 9367 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRMPI(ierr); 9368 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9369 } 9370 if (anchorIS) { 9371 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 9372 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRMPI(ierr); 9373 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9374 } 9375 9376 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 9377 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 9378 plex->anchorSection = anchorSection; 9379 9380 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 9381 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 9382 plex->anchorIS = anchorIS; 9383 9384 if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9385 PetscInt size, a, pStart, pEnd; 9386 const PetscInt *anchors; 9387 9388 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9389 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 9390 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 9391 for (a = 0; a < size; a++) { 9392 PetscInt p; 9393 9394 p = anchors[a]; 9395 if (p >= pStart && p < pEnd) { 9396 PetscInt dof; 9397 9398 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9399 if (dof) { 9400 PetscErrorCode ierr2; 9401 9402 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 9403 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 9404 } 9405 } 9406 } 9407 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 9408 } 9409 /* reset the generic constraints */ 9410 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 9411 PetscFunctionReturn(0); 9412 } 9413 9414 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9415 { 9416 PetscSection anchorSection; 9417 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9418 PetscErrorCode ierr; 9419 9420 PetscFunctionBegin; 9421 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9422 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9423 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 9424 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9425 if (numFields) { 9426 PetscInt f; 9427 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 9428 9429 for (f = 0; f < numFields; f++) { 9430 PetscInt numComp; 9431 9432 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 9433 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 9434 } 9435 } 9436 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9437 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9438 pStart = PetscMax(pStart,sStart); 9439 pEnd = PetscMin(pEnd,sEnd); 9440 pEnd = PetscMax(pStart,pEnd); 9441 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 9442 for (p = pStart; p < pEnd; p++) { 9443 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9444 if (dof) { 9445 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 9446 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 9447 for (f = 0; f < numFields; f++) { 9448 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 9449 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 9450 } 9451 } 9452 } 9453 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 9454 ierr = PetscObjectSetName((PetscObject) *cSec, "Constraint Section");CHKERRQ(ierr); 9455 PetscFunctionReturn(0); 9456 } 9457 9458 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9459 { 9460 PetscSection aSec; 9461 PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 9462 const PetscInt *anchors; 9463 PetscInt numFields, f; 9464 IS aIS; 9465 PetscErrorCode ierr; 9466 MatType mtype; 9467 PetscBool iscuda,iskokkos; 9468 9469 PetscFunctionBegin; 9470 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9471 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 9472 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 9473 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 9474 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 9475 ierr = PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr); 9476 if (!iscuda) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr); } 9477 ierr = PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos);CHKERRQ(ierr); 9478 if (!iskokkos) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos);CHKERRQ(ierr); } 9479 if (iscuda) mtype = MATSEQAIJCUSPARSE; 9480 else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9481 else mtype = MATSEQAIJ; 9482 ierr = MatSetType(*cMat,mtype);CHKERRQ(ierr); 9483 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 9484 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 9485 /* cSec will be a subset of aSec and section */ 9486 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 9487 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9488 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 9489 i[0] = 0; 9490 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9491 for (p = pStart; p < pEnd; p++) { 9492 PetscInt rDof, rOff, r; 9493 9494 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9495 if (!rDof) continue; 9496 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9497 if (numFields) { 9498 for (f = 0; f < numFields; f++) { 9499 annz = 0; 9500 for (r = 0; r < rDof; r++) { 9501 a = anchors[rOff + r]; 9502 if (a < sStart || a >= sEnd) continue; 9503 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9504 annz += aDof; 9505 } 9506 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9507 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 9508 for (q = 0; q < dof; q++) { 9509 i[off + q + 1] = i[off + q] + annz; 9510 } 9511 } 9512 } else { 9513 annz = 0; 9514 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9515 for (q = 0; q < dof; q++) { 9516 a = anchors[rOff + q]; 9517 if (a < sStart || a >= sEnd) continue; 9518 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9519 annz += aDof; 9520 } 9521 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9522 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 9523 for (q = 0; q < dof; q++) { 9524 i[off + q + 1] = i[off + q] + annz; 9525 } 9526 } 9527 } 9528 nnz = i[m]; 9529 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 9530 offset = 0; 9531 for (p = pStart; p < pEnd; p++) { 9532 if (numFields) { 9533 for (f = 0; f < numFields; f++) { 9534 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9535 for (q = 0; q < dof; q++) { 9536 PetscInt rDof, rOff, r; 9537 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9538 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9539 for (r = 0; r < rDof; r++) { 9540 PetscInt s; 9541 9542 a = anchors[rOff + r]; 9543 if (a < sStart || a >= sEnd) continue; 9544 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9545 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 9546 for (s = 0; s < aDof; s++) { 9547 j[offset++] = aOff + s; 9548 } 9549 } 9550 } 9551 } 9552 } else { 9553 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9554 for (q = 0; q < dof; q++) { 9555 PetscInt rDof, rOff, r; 9556 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9557 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9558 for (r = 0; r < rDof; r++) { 9559 PetscInt s; 9560 9561 a = anchors[rOff + r]; 9562 if (a < sStart || a >= sEnd) continue; 9563 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9564 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 9565 for (s = 0; s < aDof; s++) { 9566 j[offset++] = aOff + s; 9567 } 9568 } 9569 } 9570 } 9571 } 9572 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 9573 ierr = PetscFree(i);CHKERRQ(ierr); 9574 ierr = PetscFree(j);CHKERRQ(ierr); 9575 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 9576 PetscFunctionReturn(0); 9577 } 9578 9579 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 9580 { 9581 DM_Plex *plex = (DM_Plex *)dm->data; 9582 PetscSection anchorSection, section, cSec; 9583 Mat cMat; 9584 PetscErrorCode ierr; 9585 9586 PetscFunctionBegin; 9587 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9588 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9589 if (anchorSection) { 9590 PetscInt Nf; 9591 9592 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 9593 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 9594 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 9595 ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 9596 if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 9597 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 9598 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 9599 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 9600 } 9601 PetscFunctionReturn(0); 9602 } 9603 9604 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9605 { 9606 IS subis; 9607 PetscSection section, subsection; 9608 PetscErrorCode ierr; 9609 9610 PetscFunctionBegin; 9611 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9612 if (!section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 9613 if (!subdm) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9614 /* Create subdomain */ 9615 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 9616 /* Create submodel */ 9617 ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr); 9618 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 9619 ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr); 9620 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 9621 ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 9622 /* Create map from submodel to global model */ 9623 if (is) { 9624 PetscSection sectionGlobal, subsectionGlobal; 9625 IS spIS; 9626 const PetscInt *spmap; 9627 PetscInt *subIndices; 9628 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9629 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9630 9631 ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 9632 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 9633 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 9634 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 9635 ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 9636 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 9637 for (p = pStart; p < pEnd; ++p) { 9638 PetscInt gdof, pSubSize = 0; 9639 9640 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 9641 if (gdof > 0) { 9642 for (f = 0; f < Nf; ++f) { 9643 PetscInt fdof, fcdof; 9644 9645 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 9646 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 9647 pSubSize += fdof-fcdof; 9648 } 9649 subSize += pSubSize; 9650 if (pSubSize) { 9651 if (bs < 0) { 9652 bs = pSubSize; 9653 } else if (bs != pSubSize) { 9654 /* Layout does not admit a pointwise block size */ 9655 bs = 1; 9656 } 9657 } 9658 } 9659 } 9660 /* Must have same blocksize on all procs (some might have no points) */ 9661 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 9662 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 9663 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9664 else {bs = bsMinMax[0];} 9665 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 9666 for (p = pStart; p < pEnd; ++p) { 9667 PetscInt gdof, goff; 9668 9669 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 9670 if (gdof > 0) { 9671 const PetscInt point = spmap[p]; 9672 9673 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 9674 for (f = 0; f < Nf; ++f) { 9675 PetscInt fdof, fcdof, fc, f2, poff = 0; 9676 9677 /* Can get rid of this loop by storing field information in the global section */ 9678 for (f2 = 0; f2 < f; ++f2) { 9679 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 9680 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 9681 poff += fdof-fcdof; 9682 } 9683 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 9684 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 9685 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9686 subIndices[subOff] = goff+poff+fc; 9687 } 9688 } 9689 } 9690 } 9691 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 9692 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 9693 if (bs > 1) { 9694 /* We need to check that the block size does not come from non-contiguous fields */ 9695 PetscInt i, j, set = 1; 9696 for (i = 0; i < subSize; i += bs) { 9697 for (j = 0; j < bs; ++j) { 9698 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9699 } 9700 } 9701 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 9702 } 9703 /* Attach nullspace */ 9704 for (f = 0; f < Nf; ++f) { 9705 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9706 if ((*subdm)->nullspaceConstructors[f]) break; 9707 } 9708 if (f < Nf) { 9709 MatNullSpace nullSpace; 9710 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace);CHKERRQ(ierr); 9711 9712 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 9713 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 9714 } 9715 } 9716 PetscFunctionReturn(0); 9717 } 9718 9719 /*@ 9720 DMPlexMonitorThroughput - Report the cell throughput of FE integration 9721 9722 Input Parameter: 9723 - dm - The DM 9724 9725 Level: developer 9726 9727 Options Database Keys: 9728 . -dm_plex_monitor_throughput - Activate the monitor 9729 9730 .seealso: DMSetFromOptions(), DMPlexCreate() 9731 @*/ 9732 PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9733 { 9734 #if defined(PETSC_USE_LOG) 9735 PetscStageLog stageLog; 9736 PetscLogEvent event; 9737 PetscLogStage stage; 9738 PetscEventPerfInfo eventInfo; 9739 PetscReal cellRate, flopRate; 9740 PetscInt cStart, cEnd, Nf, N; 9741 const char *name; 9742 PetscErrorCode ierr; 9743 #endif 9744 9745 PetscFunctionBegin; 9746 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9747 #if defined(PETSC_USE_LOG) 9748 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 9749 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9750 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9751 ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 9752 ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr); 9753 ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr); 9754 ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr); 9755 N = (cEnd - cStart)*Nf*eventInfo.count; 9756 flopRate = eventInfo.flops/eventInfo.time; 9757 cellRate = N/eventInfo.time; 9758 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); 9759 #else 9760 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9761 #endif 9762 PetscFunctionReturn(0); 9763 } 9764