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