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 10 /* Logging support */ 11 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; 12 13 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 14 15 /*@ 16 DMPlexIsSimplex - Is the first cell in this mesh a simplex? 17 18 Input Parameter: 19 . dm - The DMPlex object 20 21 Output Parameter: 22 . simplex - Flag checking for a simplex 23 24 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 25 If the mesh has no cells, this returns PETSC_FALSE. 26 27 Level: intermediate 28 29 .seealso DMPlexGetSimplexOrBoxCells(), DMPlexGetCellType(), DMPlexGetHeightStratum(), DMPolytopeTypeGetNumVertices() 30 @*/ 31 PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 32 { 33 DMPolytopeType ct; 34 PetscInt cStart, cEnd; 35 PetscErrorCode ierr; 36 37 PetscFunctionBegin; 38 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 39 if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);} 40 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 41 *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 42 PetscFunctionReturn(0); 43 } 44 45 /*@ 46 DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 47 48 Input Parameter: 49 + dm - The DMPlex object 50 - height - The cell height in the Plex, 0 is the default 51 52 Output Parameters: 53 + cStart - The first "normal" cell 54 - cEnd - The upper bound on "normal"" cells 55 56 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 57 58 Level: developer 59 60 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 61 @*/ 62 PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 63 { 64 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 65 PetscInt cS, cE, c; 66 PetscErrorCode ierr; 67 68 PetscFunctionBegin; 69 ierr = DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE);CHKERRQ(ierr); 70 for (c = cS; c < cE; ++c) { 71 DMPolytopeType cct; 72 73 ierr = DMPlexGetCellType(dm, c, &cct);CHKERRQ(ierr); 74 if ((PetscInt) cct < 0) break; 75 switch (cct) { 76 case DM_POLYTOPE_POINT: 77 case DM_POLYTOPE_SEGMENT: 78 case DM_POLYTOPE_TRIANGLE: 79 case DM_POLYTOPE_QUADRILATERAL: 80 case DM_POLYTOPE_TETRAHEDRON: 81 case DM_POLYTOPE_HEXAHEDRON: 82 ct = cct; 83 break; 84 default: break; 85 } 86 if (ct != DM_POLYTOPE_UNKNOWN) break; 87 } 88 if (ct != DM_POLYTOPE_UNKNOWN) { 89 DMLabel ctLabel; 90 91 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 92 ierr = DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE);CHKERRQ(ierr); 93 } 94 if (cStart) *cStart = cS; 95 if (cEnd) *cEnd = cE; 96 PetscFunctionReturn(0); 97 } 98 99 PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 100 { 101 PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 102 PetscInt vcdof[2] = {0,0}, globalvcdof[2]; 103 PetscErrorCode ierr; 104 105 PetscFunctionBegin; 106 *ft = PETSC_VTK_INVALID; 107 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 108 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 109 ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 110 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 111 if (field >= 0) { 112 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]);CHKERRQ(ierr);} 113 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]);CHKERRQ(ierr);} 114 } else { 115 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vcdof[0]);CHKERRQ(ierr);} 116 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &vcdof[1]);CHKERRQ(ierr);} 117 } 118 ierr = MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 119 if (globalvcdof[0]) { 120 *sStart = vStart; 121 *sEnd = vEnd; 122 if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 123 else *ft = PETSC_VTK_POINT_FIELD; 124 } else if (globalvcdof[1]) { 125 *sStart = cStart; 126 *sEnd = cEnd; 127 if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 128 else *ft = PETSC_VTK_CELL_FIELD; 129 } else { 130 if (field >= 0) { 131 const char *fieldname; 132 133 ierr = PetscSectionGetFieldName(section, field, &fieldname);CHKERRQ(ierr); 134 ierr = PetscInfo2((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname);CHKERRQ(ierr); 135 } else { 136 ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\"%s\"\n");CHKERRQ(ierr); 137 } 138 } 139 PetscFunctionReturn(0); 140 } 141 142 static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 143 { 144 DM dm; 145 PetscSection s; 146 PetscDraw draw, popup; 147 DM cdm; 148 PetscSection coordSection; 149 Vec coordinates; 150 const PetscScalar *coords, *array; 151 PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 152 PetscReal vbound[2], time; 153 PetscBool isnull, flg; 154 PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 155 const char *name; 156 char title[PETSC_MAX_PATH_LEN]; 157 PetscErrorCode ierr; 158 159 PetscFunctionBegin; 160 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 161 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 162 if (isnull) PetscFunctionReturn(0); 163 164 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 165 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 166 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D. Use PETSCVIEWERGLVIS", dim); 167 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 168 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 169 ierr = DMGetCoarsenLevel(dm, &level);CHKERRQ(ierr); 170 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 171 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 172 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 173 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 174 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 175 176 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 177 ierr = DMGetOutputSequenceNumber(dm, &step, &time);CHKERRQ(ierr); 178 179 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 180 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 181 for (c = 0; c < N; c += dim) { 182 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 183 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 184 } 185 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 186 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 187 188 /* Could implement something like DMDASelectFields() */ 189 for (f = 0; f < Nf; ++f) { 190 DM fdm = dm; 191 Vec fv = v; 192 IS fis; 193 char prefix[PETSC_MAX_PATH_LEN]; 194 const char *fname; 195 196 ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr); 197 ierr = PetscSectionGetFieldName(s, f, &fname);CHKERRQ(ierr); 198 199 if (v->hdr.prefix) {ierr = PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix));CHKERRQ(ierr);} 200 else {prefix[0] = '\0';} 201 if (Nf > 1) { 202 ierr = DMCreateSubDM(dm, 1, &f, &fis, &fdm);CHKERRQ(ierr); 203 ierr = VecGetSubVector(v, fis, &fv);CHKERRQ(ierr); 204 ierr = PetscStrlcat(prefix, fname,sizeof(prefix));CHKERRQ(ierr); 205 ierr = PetscStrlcat(prefix, "_",sizeof(prefix));CHKERRQ(ierr); 206 } 207 for (comp = 0; comp < Nc; ++comp, ++w) { 208 PetscInt nmax = 2; 209 210 ierr = PetscViewerDrawGetDraw(viewer, w, &draw);CHKERRQ(ierr); 211 if (Nc > 1) {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time);CHKERRQ(ierr);} 212 else {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time);CHKERRQ(ierr);} 213 ierr = PetscDrawSetTitle(draw, title);CHKERRQ(ierr); 214 215 /* TODO Get max and min only for this component */ 216 ierr = PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg);CHKERRQ(ierr); 217 if (!flg) { 218 ierr = VecMin(fv, NULL, &vbound[0]);CHKERRQ(ierr); 219 ierr = VecMax(fv, NULL, &vbound[1]);CHKERRQ(ierr); 220 if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 221 } 222 ierr = PetscDrawGetPopup(draw, &popup);CHKERRQ(ierr); 223 ierr = PetscDrawScalePopup(popup, vbound[0], vbound[1]);CHKERRQ(ierr); 224 ierr = PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]);CHKERRQ(ierr); 225 226 ierr = VecGetArrayRead(fv, &array);CHKERRQ(ierr); 227 for (c = cStart; c < cEnd; ++c) { 228 PetscScalar *coords = NULL, *a = NULL; 229 PetscInt numCoords, color[4] = {-1,-1,-1,-1}; 230 231 ierr = DMPlexPointLocalRead(fdm, c, array, &a);CHKERRQ(ierr); 232 if (a) { 233 color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 234 color[1] = color[2] = color[3] = color[0]; 235 } else { 236 PetscScalar *vals = NULL; 237 PetscInt numVals, va; 238 239 ierr = DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 240 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); 241 switch (numVals/Nc) { 242 case 3: /* P1 Triangle */ 243 case 4: /* P1 Quadrangle */ 244 for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]); 245 break; 246 case 6: /* P2 Triangle */ 247 case 8: /* P2 Quadrangle */ 248 for (va = 0; va < numVals/(Nc*2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp + numVals/(Nc*2)]), vbound[0], vbound[1]); 249 break; 250 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc); 251 } 252 ierr = DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 253 } 254 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 255 switch (numCoords) { 256 case 6: 257 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); 258 break; 259 case 8: 260 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); 261 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); 262 break; 263 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords); 264 } 265 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 266 } 267 ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr); 268 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 269 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 270 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 271 } 272 if (Nf > 1) { 273 ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr); 274 ierr = ISDestroy(&fis);CHKERRQ(ierr); 275 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 276 } 277 } 278 PetscFunctionReturn(0); 279 } 280 281 static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 282 { 283 DM dm; 284 Vec locv; 285 const char *name; 286 PetscSection section; 287 PetscInt pStart, pEnd; 288 PetscInt numFields; 289 PetscViewerVTKFieldType ft; 290 PetscErrorCode ierr; 291 292 PetscFunctionBegin; 293 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 294 ierr = DMCreateLocalVector(dm, &locv);CHKERRQ(ierr); /* VTK viewer requires exclusive ownership of the vector */ 295 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 296 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 297 ierr = VecCopy(v, locv);CHKERRQ(ierr); 298 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 299 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 300 if (!numFields) { 301 ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 302 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 303 } else { 304 PetscInt f; 305 306 for (f = 0; f < numFields; f++) { 307 ierr = DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft);CHKERRQ(ierr); 308 if (ft == PETSC_VTK_INVALID) continue; 309 ierr = PetscObjectReference((PetscObject)locv);CHKERRQ(ierr); 310 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 311 } 312 ierr = VecDestroy(&locv);CHKERRQ(ierr); 313 } 314 PetscFunctionReturn(0); 315 } 316 317 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 318 { 319 DM dm; 320 PetscBool isvtk, ishdf5, isdraw, isglvis; 321 PetscErrorCode ierr; 322 323 PetscFunctionBegin; 324 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 325 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 326 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 327 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 328 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 329 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 330 if (isvtk || ishdf5 || isdraw || isglvis) { 331 PetscInt i,numFields; 332 PetscObject fe; 333 PetscBool fem = PETSC_FALSE; 334 Vec locv = v; 335 const char *name; 336 PetscInt step; 337 PetscReal time; 338 339 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 340 for (i=0; i<numFields; i++) { 341 ierr = DMGetField(dm, i, NULL, &fe);CHKERRQ(ierr); 342 if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; } 343 } 344 if (fem) { 345 PetscObject isZero; 346 347 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 348 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 349 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 350 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 351 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 352 ierr = VecCopy(v, locv);CHKERRQ(ierr); 353 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 354 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr); 355 } 356 if (isvtk) { 357 ierr = VecView_Plex_Local_VTK(locv, viewer);CHKERRQ(ierr); 358 } else if (ishdf5) { 359 #if defined(PETSC_HAVE_HDF5) 360 ierr = VecView_Plex_Local_HDF5_Internal(locv, viewer);CHKERRQ(ierr); 361 #else 362 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 363 #endif 364 } else if (isdraw) { 365 ierr = VecView_Plex_Local_Draw(locv, viewer);CHKERRQ(ierr); 366 } else if (isglvis) { 367 ierr = DMGetOutputSequenceNumber(dm, &step, NULL);CHKERRQ(ierr); 368 ierr = PetscViewerGLVisSetSnapId(viewer, step);CHKERRQ(ierr); 369 ierr = VecView_GLVis(locv, viewer);CHKERRQ(ierr); 370 } 371 if (fem) { 372 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 373 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 374 } 375 } else { 376 PetscBool isseq; 377 378 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 379 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 380 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 381 } 382 PetscFunctionReturn(0); 383 } 384 385 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 386 { 387 DM dm; 388 PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii; 389 PetscErrorCode ierr; 390 391 PetscFunctionBegin; 392 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 393 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 394 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 395 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 396 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 397 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 398 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 399 if (isvtk || isdraw || isglvis) { 400 Vec locv; 401 PetscObject isZero; 402 const char *name; 403 404 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 405 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 406 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 407 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 408 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 409 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 410 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 411 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 412 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 413 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 414 } else if (ishdf5) { 415 #if defined(PETSC_HAVE_HDF5) 416 ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 417 #else 418 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 419 #endif 420 } else if (isexodusii) { 421 #if defined(PETSC_HAVE_EXODUSII) 422 ierr = VecView_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 423 #else 424 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 425 #endif 426 } else { 427 PetscBool isseq; 428 429 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 430 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 431 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 432 } 433 PetscFunctionReturn(0); 434 } 435 436 PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 437 { 438 DM dm; 439 MPI_Comm comm; 440 PetscViewerFormat format; 441 Vec v; 442 PetscBool isvtk, ishdf5; 443 PetscErrorCode ierr; 444 445 PetscFunctionBegin; 446 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 447 ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 448 if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 449 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 450 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 451 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 452 if (format == PETSC_VIEWER_NATIVE) { 453 /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 454 /* this need a better fix */ 455 if (dm->useNatural) { 456 if (dm->sfNatural) { 457 const char *vecname; 458 PetscInt n, nroots; 459 460 ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr); 461 ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 462 if (n == nroots) { 463 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 464 ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 465 ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 466 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 467 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 468 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 469 } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 470 } else v = originalv; 471 } else v = originalv; 472 473 if (ishdf5) { 474 #if defined(PETSC_HAVE_HDF5) 475 ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 476 #else 477 SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 478 #endif 479 } else if (isvtk) { 480 SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 481 } else { 482 PetscBool isseq; 483 484 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 485 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 486 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 487 } 488 if (v != originalv) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 489 PetscFunctionReturn(0); 490 } 491 492 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 493 { 494 DM dm; 495 PetscBool ishdf5; 496 PetscErrorCode ierr; 497 498 PetscFunctionBegin; 499 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 500 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 501 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 502 if (ishdf5) { 503 DM dmBC; 504 Vec gv; 505 const char *name; 506 507 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 508 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 509 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 510 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 511 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 512 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 513 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 514 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 515 } else { 516 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 517 } 518 PetscFunctionReturn(0); 519 } 520 521 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 522 { 523 DM dm; 524 PetscBool ishdf5,isexodusii; 525 PetscErrorCode ierr; 526 527 PetscFunctionBegin; 528 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 529 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 530 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 531 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 532 if (ishdf5) { 533 #if defined(PETSC_HAVE_HDF5) 534 ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 535 #else 536 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 537 #endif 538 } else if (isexodusii) { 539 #if defined(PETSC_HAVE_EXODUSII) 540 ierr = VecLoad_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 541 #else 542 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 543 #endif 544 } else { 545 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 546 } 547 PetscFunctionReturn(0); 548 } 549 550 PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 551 { 552 DM dm; 553 PetscViewerFormat format; 554 PetscBool ishdf5; 555 PetscErrorCode ierr; 556 557 PetscFunctionBegin; 558 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 559 if (!dm) SETERRQ(PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 560 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 561 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 562 if (format == PETSC_VIEWER_NATIVE) { 563 if (dm->useNatural) { 564 if (dm->sfNatural) { 565 if (ishdf5) { 566 #if defined(PETSC_HAVE_HDF5) 567 Vec v; 568 const char *vecname; 569 570 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 571 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 572 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 573 ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 574 ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 575 ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 576 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 577 #else 578 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 579 #endif 580 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 581 } 582 } else { 583 ierr = VecLoad_Default(originalv, viewer);CHKERRQ(ierr); 584 } 585 } 586 PetscFunctionReturn(0); 587 } 588 589 PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 590 { 591 PetscSection coordSection; 592 Vec coordinates; 593 DMLabel depthLabel, celltypeLabel; 594 const char *name[4]; 595 const PetscScalar *a; 596 PetscInt dim, pStart, pEnd, cStart, cEnd, c; 597 PetscErrorCode ierr; 598 599 PetscFunctionBegin; 600 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 601 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 602 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 603 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 604 ierr = DMPlexGetCellTypeLabel(dm, &celltypeLabel);CHKERRQ(ierr); 605 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 606 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 607 ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 608 name[0] = "vertex"; 609 name[1] = "edge"; 610 name[dim-1] = "face"; 611 name[dim] = "cell"; 612 for (c = cStart; c < cEnd; ++c) { 613 PetscInt *closure = NULL; 614 PetscInt closureSize, cl, ct; 615 616 ierr = DMLabelGetValue(celltypeLabel, c, &ct);CHKERRQ(ierr); 617 ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]);CHKERRQ(ierr); 618 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 619 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 620 for (cl = 0; cl < closureSize*2; cl += 2) { 621 PetscInt point = closure[cl], depth, dof, off, d, p; 622 623 if ((point < pStart) || (point >= pEnd)) continue; 624 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 625 if (!dof) continue; 626 ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 627 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 628 ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr); 629 for (p = 0; p < dof/dim; ++p) { 630 ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 631 for (d = 0; d < dim; ++d) { 632 if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 633 ierr = PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 634 } 635 ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 636 } 637 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 638 } 639 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 640 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 641 } 642 ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 643 PetscFunctionReturn(0); 644 } 645 646 static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 647 { 648 DM_Plex *mesh = (DM_Plex*) dm->data; 649 DM cdm; 650 PetscSection coordSection; 651 Vec coordinates; 652 PetscViewerFormat format; 653 PetscErrorCode ierr; 654 655 PetscFunctionBegin; 656 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 657 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 658 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 659 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 660 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 661 const char *name; 662 PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 663 PetscInt pStart, pEnd, p, numLabels, l; 664 PetscMPIInt rank, size; 665 666 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 667 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 668 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 669 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 670 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 671 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 672 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 673 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 674 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 675 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 676 ierr = PetscViewerASCIIPrintf(viewer, "Supports:\n", name);CHKERRQ(ierr); 677 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 678 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize);CHKERRQ(ierr); 679 for (p = pStart; p < pEnd; ++p) { 680 PetscInt dof, off, s; 681 682 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 683 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 684 for (s = off; s < off+dof; ++s) { 685 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 686 } 687 } 688 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 689 ierr = PetscViewerASCIIPrintf(viewer, "Cones:\n", name);CHKERRQ(ierr); 690 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize);CHKERRQ(ierr); 691 for (p = pStart; p < pEnd; ++p) { 692 PetscInt dof, off, c; 693 694 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 695 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 696 for (c = off; c < off+dof; ++c) { 697 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 698 } 699 } 700 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 701 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 702 if (coordSection && coordinates) { 703 ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr); 704 } 705 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 706 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 707 for (l = 0; l < numLabels; ++l) { 708 DMLabel label; 709 PetscBool isdepth; 710 const char *name; 711 712 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 713 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 714 if (isdepth) continue; 715 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 716 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 717 } 718 if (size > 1) { 719 PetscSF sf; 720 721 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 722 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 723 } 724 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 725 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 726 const char *name, *color; 727 const char *defcolors[3] = {"gray", "orange", "green"}; 728 const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 729 char lname[PETSC_MAX_PATH_LEN]; 730 PetscReal scale = 2.0; 731 PetscReal tikzscale = 1.0; 732 PetscBool useNumbers = PETSC_TRUE, useLabels, useColors; 733 double tcoords[3]; 734 PetscScalar *coords; 735 PetscInt numLabels, l, numColors, numLColors, dim, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 736 PetscMPIInt rank, size; 737 char **names, **colors, **lcolors; 738 PetscBool plotEdges, flg, lflg; 739 PetscBT wp = NULL; 740 PetscInt pEnd, pStart; 741 742 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 743 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 744 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 745 numLabels = PetscMax(numLabels, 10); 746 numColors = 10; 747 numLColors = 10; 748 ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 749 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 750 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL);CHKERRQ(ierr); 751 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 752 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 753 if (!useLabels) numLabels = 0; 754 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 755 if (!useColors) { 756 numColors = 3; 757 for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 758 } 759 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 760 if (!useColors) { 761 numLColors = 4; 762 for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 763 } 764 ierr = PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg);CHKERRQ(ierr); 765 plotEdges = (PetscBool)(depth > 1 && useNumbers && dim < 3); 766 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg);CHKERRQ(ierr); 767 if (flg && plotEdges && depth < dim) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 768 if (depth < dim) plotEdges = PETSC_FALSE; 769 770 /* filter points with labelvalue != labeldefaultvalue */ 771 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 772 if (lflg) { 773 DMLabel lbl; 774 775 ierr = DMGetLabel(dm, lname, &lbl);CHKERRQ(ierr); 776 if (lbl) { 777 PetscInt val, defval; 778 779 ierr = DMLabelGetDefaultValue(lbl, &defval);CHKERRQ(ierr); 780 ierr = PetscBTCreate(pEnd-pStart, &wp);CHKERRQ(ierr); 781 for (c = pStart; c < pEnd; c++) { 782 PetscInt *closure = NULL; 783 PetscInt closureSize; 784 785 ierr = DMLabelGetValue(lbl, c, &val);CHKERRQ(ierr); 786 if (val == defval) continue; 787 788 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 789 for (p = 0; p < closureSize*2; p += 2) { 790 ierr = PetscBTSet(wp, closure[p] - pStart);CHKERRQ(ierr); 791 } 792 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 793 } 794 } 795 } 796 797 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 798 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 799 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 800 ierr = PetscViewerASCIIPrintf(viewer, "\ 801 \\documentclass[tikz]{standalone}\n\n\ 802 \\usepackage{pgflibraryshapes}\n\ 803 \\usetikzlibrary{backgrounds}\n\ 804 \\usetikzlibrary{arrows}\n\ 805 \\begin{document}\n");CHKERRQ(ierr); 806 if (size > 1) { 807 ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 808 for (p = 0; p < size; ++p) { 809 if (p > 0 && p == size-1) { 810 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 811 } else if (p > 0) { 812 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 813 } 814 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 815 } 816 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 817 } 818 ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale);CHKERRQ(ierr); 819 820 /* Plot vertices */ 821 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 822 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 823 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 824 for (v = vStart; v < vEnd; ++v) { 825 PetscInt off, dof, d; 826 PetscBool isLabeled = PETSC_FALSE; 827 828 if (wp && !PetscBTLookup(wp,v - pStart)) continue; 829 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 830 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 831 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 832 if (PetscUnlikely(dof > 3)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 833 for (d = 0; d < dof; ++d) { 834 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 835 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 836 } 837 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 838 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 839 for (d = 0; d < dof; ++d) { 840 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 841 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]);CHKERRQ(ierr); 842 } 843 color = colors[rank%numColors]; 844 for (l = 0; l < numLabels; ++l) { 845 PetscInt val; 846 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 847 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 848 } 849 if (useNumbers) { 850 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 851 } else { 852 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 853 } 854 } 855 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 856 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 857 /* Plot cells */ 858 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 859 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 860 if (dim == 3 || !useNumbers) { 861 for (e = eStart; e < eEnd; ++e) { 862 const PetscInt *cone; 863 864 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 865 color = colors[rank%numColors]; 866 for (l = 0; l < numLabels; ++l) { 867 PetscInt val; 868 ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 869 if (val >= 0) {color = lcolors[l%numLColors]; break;} 870 } 871 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 872 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 873 } 874 } else { 875 for (c = cStart; c < cEnd; ++c) { 876 PetscInt *closure = NULL; 877 PetscInt closureSize, firstPoint = -1; 878 879 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 880 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 881 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 882 for (p = 0; p < closureSize*2; p += 2) { 883 const PetscInt point = closure[p]; 884 885 if ((point < vStart) || (point >= vEnd)) continue; 886 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 887 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", point, rank);CHKERRQ(ierr); 888 if (firstPoint < 0) firstPoint = point; 889 } 890 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 891 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d);\n", firstPoint, rank);CHKERRQ(ierr); 892 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 893 } 894 } 895 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 896 for (c = cStart; c < cEnd; ++c) { 897 double ccoords[3] = {0.0, 0.0, 0.0}; 898 PetscBool isLabeled = PETSC_FALSE; 899 PetscInt *closure = NULL; 900 PetscInt closureSize, dof, d, n = 0; 901 902 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 903 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 904 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 905 for (p = 0; p < closureSize*2; p += 2) { 906 const PetscInt point = closure[p]; 907 PetscInt off; 908 909 if ((point < vStart) || (point >= vEnd)) continue; 910 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 911 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 912 for (d = 0; d < dof; ++d) { 913 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 914 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 915 } 916 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 917 if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 918 for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 919 ++n; 920 } 921 for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 922 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 923 for (d = 0; d < dof; ++d) { 924 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 925 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]);CHKERRQ(ierr); 926 } 927 color = colors[rank%numColors]; 928 for (l = 0; l < numLabels; ++l) { 929 PetscInt val; 930 ierr = DMGetLabelValue(dm, names[l], c, &val);CHKERRQ(ierr); 931 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 932 } 933 if (useNumbers) { 934 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c);CHKERRQ(ierr); 935 } else { 936 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 937 } 938 } 939 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 940 /* Plot edges */ 941 if (plotEdges) { 942 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 943 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 944 for (e = eStart; e < eEnd; ++e) { 945 const PetscInt *cone; 946 PetscInt coneSize, offA, offB, dof, d; 947 948 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 949 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 950 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 951 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 952 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 953 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 954 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 955 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 956 for (d = 0; d < dof; ++d) { 957 tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 958 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 959 } 960 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 961 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 962 for (d = 0; d < dof; ++d) { 963 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 964 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr); 965 } 966 color = colors[rank%numColors]; 967 for (l = 0; l < numLabels; ++l) { 968 PetscInt val; 969 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 970 if (val >= 0) {color = lcolors[l%numLColors]; break;} 971 } 972 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 973 } 974 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 975 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 976 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 977 } 978 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 979 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 980 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 981 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 982 for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 983 for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 984 for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 985 ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 986 ierr = PetscBTDestroy(&wp);CHKERRQ(ierr); 987 } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 988 Vec cown,acown; 989 VecScatter sct; 990 ISLocalToGlobalMapping g2l; 991 IS gid,acis; 992 MPI_Comm comm,ncomm = MPI_COMM_NULL; 993 MPI_Group ggroup,ngroup; 994 PetscScalar *array,nid; 995 const PetscInt *idxs; 996 PetscInt *idxs2,*start,*adjacency,*work; 997 PetscInt64 lm[3],gm[3]; 998 PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 999 PetscMPIInt d1,d2,rank; 1000 1001 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1002 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 1003 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1004 ierr = MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm);CHKERRMPI(ierr); 1005 #endif 1006 if (ncomm != MPI_COMM_NULL) { 1007 ierr = MPI_Comm_group(comm,&ggroup);CHKERRMPI(ierr); 1008 ierr = MPI_Comm_group(ncomm,&ngroup);CHKERRMPI(ierr); 1009 d1 = 0; 1010 ierr = MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2);CHKERRMPI(ierr); 1011 nid = d2; 1012 ierr = MPI_Group_free(&ggroup);CHKERRMPI(ierr); 1013 ierr = MPI_Group_free(&ngroup);CHKERRMPI(ierr); 1014 ierr = MPI_Comm_free(&ncomm);CHKERRMPI(ierr); 1015 } else nid = 0.0; 1016 1017 /* Get connectivity */ 1018 ierr = DMPlexGetVTKCellHeight(dm,&cellHeight);CHKERRQ(ierr); 1019 ierr = DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid);CHKERRQ(ierr); 1020 1021 /* filter overlapped local cells */ 1022 ierr = DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd);CHKERRQ(ierr); 1023 ierr = ISGetIndices(gid,&idxs);CHKERRQ(ierr); 1024 ierr = ISGetLocalSize(gid,&cum);CHKERRQ(ierr); 1025 ierr = PetscMalloc1(cum,&idxs2);CHKERRQ(ierr); 1026 for (c = cStart, cum = 0; c < cEnd; c++) { 1027 if (idxs[c-cStart] < 0) continue; 1028 idxs2[cum++] = idxs[c-cStart]; 1029 } 1030 ierr = ISRestoreIndices(gid,&idxs);CHKERRQ(ierr); 1031 if (numVertices != cum) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum); 1032 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1033 ierr = ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid);CHKERRQ(ierr); 1034 1035 /* support for node-aware cell locality */ 1036 ierr = ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis);CHKERRQ(ierr); 1037 ierr = VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown);CHKERRQ(ierr); 1038 ierr = VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown);CHKERRQ(ierr); 1039 ierr = VecGetArray(cown,&array);CHKERRQ(ierr); 1040 for (c = 0; c < numVertices; c++) array[c] = nid; 1041 ierr = VecRestoreArray(cown,&array);CHKERRQ(ierr); 1042 ierr = VecScatterCreate(cown,acis,acown,NULL,&sct);CHKERRQ(ierr); 1043 ierr = VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1044 ierr = VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1045 ierr = ISDestroy(&acis);CHKERRQ(ierr); 1046 ierr = VecScatterDestroy(&sct);CHKERRQ(ierr); 1047 ierr = VecDestroy(&cown);CHKERRQ(ierr); 1048 1049 /* compute edgeCut */ 1050 for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 1051 ierr = PetscMalloc1(cum,&work);CHKERRQ(ierr); 1052 ierr = ISLocalToGlobalMappingCreateIS(gid,&g2l);CHKERRQ(ierr); 1053 ierr = ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 1054 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1055 ierr = VecGetArray(acown,&array);CHKERRQ(ierr); 1056 for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 1057 PetscInt totl; 1058 1059 totl = start[c+1]-start[c]; 1060 ierr = ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work);CHKERRQ(ierr); 1061 for (i = 0; i < totl; i++) { 1062 if (work[i] < 0) { 1063 ect += 1; 1064 ectn += (array[i + start[c]] != nid) ? 0 : 1; 1065 } 1066 } 1067 } 1068 ierr = PetscFree(work);CHKERRQ(ierr); 1069 ierr = VecRestoreArray(acown,&array);CHKERRQ(ierr); 1070 lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 1071 lm[1] = -numVertices; 1072 ierr = MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm);CHKERRMPI(ierr); 1073 ierr = PetscViewerASCIIPrintf(viewer," Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]);CHKERRQ(ierr); 1074 lm[0] = ect; /* edgeCut */ 1075 lm[1] = ectn; /* node-aware edgeCut */ 1076 lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 1077 ierr = MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr); 1078 ierr = PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]);CHKERRQ(ierr); 1079 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1080 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); 1081 #else 1082 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0);CHKERRQ(ierr); 1083 #endif 1084 ierr = ISLocalToGlobalMappingDestroy(&g2l);CHKERRQ(ierr); 1085 ierr = PetscFree(start);CHKERRQ(ierr); 1086 ierr = PetscFree(adjacency);CHKERRQ(ierr); 1087 ierr = VecDestroy(&acown);CHKERRQ(ierr); 1088 } else { 1089 const char *name; 1090 PetscInt *sizes, *hybsizes, *ghostsizes; 1091 PetscInt locDepth, depth, cellHeight, dim, d; 1092 PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1093 PetscInt numLabels, l; 1094 DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1095 MPI_Comm comm; 1096 PetscMPIInt size, rank; 1097 1098 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1099 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1100 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1101 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1102 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 1103 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 1104 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1105 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1106 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 1107 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 1108 ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRMPI(ierr); 1109 ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr); 1110 gcNum = gcEnd - gcStart; 1111 ierr = PetscCalloc3(size,&sizes,size,&hybsizes,size,&ghostsizes);CHKERRQ(ierr); 1112 for (d = 0; d <= depth; d++) { 1113 PetscInt Nc[2] = {0, 0}, ict; 1114 1115 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 1116 if (pStart < pEnd) {ierr = DMPlexGetCellType(dm, pStart, &ct0);CHKERRQ(ierr);} 1117 ict = ct0; 1118 ierr = MPI_Bcast(&ict, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1119 ct0 = (DMPolytopeType) ict; 1120 for (p = pStart; p < pEnd; ++p) { 1121 DMPolytopeType ct; 1122 1123 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 1124 if (ct == ct0) ++Nc[0]; 1125 else ++Nc[1]; 1126 } 1127 ierr = MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1128 ierr = MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1129 if (d == depth) {ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);} 1130 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", (depth == 1) && d ? dim : d);CHKERRQ(ierr); 1131 for (p = 0; p < size; ++p) { 1132 if (!rank) { 1133 ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]);CHKERRQ(ierr); 1134 if (hybsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]);CHKERRQ(ierr);} 1135 if (ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);} 1136 } 1137 } 1138 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 1139 } 1140 ierr = PetscFree3(sizes,hybsizes,ghostsizes);CHKERRQ(ierr); 1141 { 1142 const PetscReal *maxCell; 1143 const PetscReal *L; 1144 const DMBoundaryType *bd; 1145 PetscBool per, localized; 1146 1147 ierr = DMGetPeriodicity(dm, &per, &maxCell, &L, &bd);CHKERRQ(ierr); 1148 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 1149 if (per) { 1150 ierr = PetscViewerASCIIPrintf(viewer, "Periodic mesh (");CHKERRQ(ierr); 1151 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1152 for (d = 0; d < dim; ++d) { 1153 if (bd && d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1154 if (bd) {ierr = PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]]);CHKERRQ(ierr);} 1155 } 1156 ierr = PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized");CHKERRQ(ierr); 1157 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1158 } 1159 } 1160 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 1161 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 1162 for (l = 0; l < numLabels; ++l) { 1163 DMLabel label; 1164 const char *name; 1165 IS valueIS; 1166 const PetscInt *values; 1167 PetscInt numValues, v; 1168 1169 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 1170 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1171 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 1172 ierr = PetscViewerASCIIPrintf(viewer, " %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr); 1173 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 1174 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 1175 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1176 for (v = 0; v < numValues; ++v) { 1177 PetscInt size; 1178 1179 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 1180 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1181 ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr); 1182 } 1183 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 1184 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1185 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 1186 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 1187 } 1188 /* If no fields are specified, people do not want to see adjacency */ 1189 if (dm->Nf) { 1190 PetscInt f; 1191 1192 for (f = 0; f < dm->Nf; ++f) { 1193 const char *name; 1194 1195 ierr = PetscObjectGetName(dm->fields[f].disc, &name);CHKERRQ(ierr); 1196 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Field %s:\n", name);CHKERRQ(ierr);} 1197 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1198 if (dm->fields[f].label) {ierr = DMLabelView(dm->fields[f].label, viewer);CHKERRQ(ierr);} 1199 if (dm->fields[f].adjacency[0]) { 1200 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n");CHKERRQ(ierr);} 1201 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM\n");CHKERRQ(ierr);} 1202 } else { 1203 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FEM\n");CHKERRQ(ierr);} 1204 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n");CHKERRQ(ierr);} 1205 } 1206 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1207 } 1208 } 1209 ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr); 1210 if (cdm) { 1211 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1212 ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr); 1213 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1214 } 1215 } 1216 PetscFunctionReturn(0); 1217 } 1218 1219 static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1220 { 1221 DMPolytopeType ct; 1222 PetscMPIInt rank; 1223 PetscErrorCode ierr; 1224 1225 PetscFunctionBegin; 1226 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1227 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1228 switch (ct) { 1229 case DM_POLYTOPE_TRIANGLE: 1230 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1231 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1232 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1233 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1234 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1235 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1236 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1237 break; 1238 case DM_POLYTOPE_QUADRILATERAL: 1239 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1240 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1241 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1242 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1243 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1244 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1245 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1246 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1247 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1248 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1249 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1250 ierr = PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1251 break; 1252 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1253 } 1254 PetscFunctionReturn(0); 1255 } 1256 1257 static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1258 { 1259 DMPolytopeType ct; 1260 PetscReal centroid[2] = {0., 0.}; 1261 PetscMPIInt rank; 1262 PetscInt fillColor, v, e, d; 1263 PetscErrorCode ierr; 1264 1265 PetscFunctionBegin; 1266 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1267 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1268 fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2; 1269 switch (ct) { 1270 case DM_POLYTOPE_TRIANGLE: 1271 { 1272 PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1273 1274 for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;} 1275 for (e = 0; e < 3; ++e) { 1276 refCoords[0] = refVertices[e*2+0]; 1277 refCoords[1] = refVertices[e*2+1]; 1278 for (d = 1; d <= edgeDiv; ++d) { 1279 refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv; 1280 refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv; 1281 } 1282 ierr = DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords);CHKERRQ(ierr); 1283 for (d = 0; d < edgeDiv; ++d) { 1284 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); 1285 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); 1286 } 1287 } 1288 } 1289 break; 1290 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1291 } 1292 PetscFunctionReturn(0); 1293 } 1294 1295 static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1296 { 1297 PetscDraw draw; 1298 DM cdm; 1299 PetscSection coordSection; 1300 Vec coordinates; 1301 const PetscScalar *coords; 1302 PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1303 PetscReal *refCoords, *edgeCoords; 1304 PetscBool isnull, drawAffine = PETSC_TRUE; 1305 PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1306 PetscErrorCode ierr; 1307 1308 PetscFunctionBegin; 1309 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 1310 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim); 1311 ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL);CHKERRQ(ierr); 1312 if (!drawAffine) {ierr = PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords);CHKERRQ(ierr);} 1313 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 1314 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1315 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 1316 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1317 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1318 1319 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 1320 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 1321 if (isnull) PetscFunctionReturn(0); 1322 ierr = PetscDrawSetTitle(draw, "Mesh");CHKERRQ(ierr); 1323 1324 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 1325 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 1326 for (c = 0; c < N; c += dim) { 1327 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 1328 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1329 } 1330 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 1331 ierr = MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1332 ierr = MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1333 ierr = PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]);CHKERRQ(ierr); 1334 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 1335 1336 for (c = cStart; c < cEnd; ++c) { 1337 PetscScalar *coords = NULL; 1338 PetscInt numCoords; 1339 1340 ierr = DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords);CHKERRQ(ierr); 1341 if (drawAffine) { 1342 ierr = DMPlexDrawCell(dm, draw, c, coords);CHKERRQ(ierr); 1343 } else { 1344 ierr = DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords);CHKERRQ(ierr); 1345 } 1346 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 1347 } 1348 if (!drawAffine) {ierr = PetscFree2(refCoords, edgeCoords);CHKERRQ(ierr);} 1349 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1350 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 1351 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 1352 PetscFunctionReturn(0); 1353 } 1354 1355 #if defined(PETSC_HAVE_EXODUSII) 1356 #include <exodusII.h> 1357 #include <petscviewerexodusii.h> 1358 #endif 1359 1360 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1361 { 1362 PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1363 char name[PETSC_MAX_PATH_LEN]; 1364 PetscErrorCode ierr; 1365 1366 PetscFunctionBegin; 1367 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1368 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1369 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1370 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1371 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1372 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 1373 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 1374 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus);CHKERRQ(ierr); 1375 if (iascii) { 1376 PetscViewerFormat format; 1377 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1378 if (format == PETSC_VIEWER_ASCII_GLVIS) { 1379 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1380 } else { 1381 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 1382 } 1383 } else if (ishdf5) { 1384 #if defined(PETSC_HAVE_HDF5) 1385 ierr = DMPlexView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1386 #else 1387 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1388 #endif 1389 } else if (isvtk) { 1390 ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr); 1391 } else if (isdraw) { 1392 ierr = DMPlexView_Draw(dm, viewer);CHKERRQ(ierr); 1393 } else if (isglvis) { 1394 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1395 #if defined(PETSC_HAVE_EXODUSII) 1396 } else if (isexodus) { 1397 /* 1398 exodusII requires that all sets be part of exactly one cell set. 1399 If the dm does not have a "Cell Sets" label defined, we create one 1400 with ID 1, containig all cells. 1401 Note that if the Cell Sets label is defined but does not cover all cells, 1402 we may still have a problem. This should probably be checked here or in the viewer; 1403 */ 1404 PetscInt numCS; 1405 ierr = DMGetLabelSize(dm,"Cell Sets",&numCS);CHKERRQ(ierr); 1406 if (!numCS){ 1407 PetscInt cStart, cEnd, c; 1408 ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr); 1409 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1410 for (c = cStart; c < cEnd; ++c) {ierr = DMSetLabelValue(dm, "Cell Sets", c, 1);CHKERRQ(ierr);} 1411 } 1412 ierr = DMView_PlexExodusII(dm, viewer);CHKERRQ(ierr); 1413 #endif 1414 } else { 1415 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1416 } 1417 /* Optionally view the partition */ 1418 ierr = PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg);CHKERRQ(ierr); 1419 if (flg) { 1420 Vec ranks; 1421 ierr = DMPlexCreateRankField(dm, &ranks);CHKERRQ(ierr); 1422 ierr = VecView(ranks, viewer);CHKERRQ(ierr); 1423 ierr = VecDestroy(&ranks);CHKERRQ(ierr); 1424 } 1425 /* Optionally view a label */ 1426 ierr = PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg);CHKERRQ(ierr); 1427 if (flg) { 1428 DMLabel label; 1429 Vec val; 1430 1431 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1432 if (!label) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 1433 ierr = DMPlexCreateLabelField(dm, label, &val);CHKERRQ(ierr); 1434 ierr = VecView(val, viewer);CHKERRQ(ierr); 1435 ierr = VecDestroy(&val);CHKERRQ(ierr); 1436 } 1437 PetscFunctionReturn(0); 1438 } 1439 1440 PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 1441 { 1442 PetscBool ishdf5; 1443 PetscErrorCode ierr; 1444 1445 PetscFunctionBegin; 1446 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1447 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1448 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1449 if (ishdf5) { 1450 #if defined(PETSC_HAVE_HDF5) 1451 PetscViewerFormat format; 1452 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1453 if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 1454 ierr = DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer);CHKERRQ(ierr); 1455 } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1456 ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1457 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1458 PetscFunctionReturn(0); 1459 #else 1460 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1461 #endif 1462 } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 1463 } 1464 1465 /*@ 1466 DMPlexTopologyLoad - Loads a topology into a DMPlex 1467 1468 Collective on DM 1469 1470 Input Parameters: 1471 + dm - The DM into which the topology is loaded 1472 - viewer - The PetscViewer for the saved topology 1473 1474 Output Parameters: 1475 . sf - 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 1476 1477 Level: advanced 1478 1479 .seealso: DMLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1480 @*/ 1481 PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *sf) 1482 { 1483 PetscBool ishdf5; 1484 PetscErrorCode ierr; 1485 1486 PetscFunctionBegin; 1487 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1488 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1489 PetscValidPointer(sf, 3); 1490 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1491 if (ishdf5) { 1492 #if defined(PETSC_HAVE_HDF5) 1493 PetscViewerFormat format; 1494 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1495 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1496 ierr = DMPlexTopologyLoad_HDF5_Internal(dm, viewer, sf);CHKERRQ(ierr); 1497 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1498 #else 1499 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1500 #endif 1501 } 1502 PetscFunctionReturn(0); 1503 } 1504 1505 /*@ 1506 DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 1507 1508 Collective on DM 1509 1510 Input Parameters: 1511 + dm - The DM into which the coordinates are loaded 1512 - viewer - The PetscViewer for the saved coordinates 1513 1514 Level: advanced 1515 1516 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1517 @*/ 1518 PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer) 1519 { 1520 PetscBool ishdf5; 1521 PetscErrorCode ierr; 1522 1523 PetscFunctionBegin; 1524 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1525 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1526 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1527 if (ishdf5) { 1528 #if defined(PETSC_HAVE_HDF5) 1529 PetscViewerFormat format; 1530 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1531 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1532 ierr = DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1533 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1534 #else 1535 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1536 #endif 1537 } 1538 PetscFunctionReturn(0); 1539 } 1540 1541 /*@ 1542 DMPlexLabelsLoad - Loads labels into a DMPlex 1543 1544 Collective on DM 1545 1546 Input Parameters: 1547 + dm - The DM into which the labels are loaded 1548 - viewer - The PetscViewer for the saved labels 1549 1550 Level: advanced 1551 1552 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1553 @*/ 1554 PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer) 1555 { 1556 PetscBool ishdf5; 1557 PetscErrorCode ierr; 1558 1559 PetscFunctionBegin; 1560 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1561 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1562 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1563 if (ishdf5) { 1564 #if defined(PETSC_HAVE_HDF5) 1565 PetscViewerFormat format; 1566 1567 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1568 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1569 ierr = DMPlexLabelsLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1570 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1571 #else 1572 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1573 #endif 1574 } 1575 PetscFunctionReturn(0); 1576 } 1577 1578 PetscErrorCode DMDestroy_Plex(DM dm) 1579 { 1580 DM_Plex *mesh = (DM_Plex*) dm->data; 1581 PetscErrorCode ierr; 1582 1583 PetscFunctionBegin; 1584 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr); 1585 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr); 1586 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL);CHKERRQ(ierr); 1587 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL);CHKERRQ(ierr); 1588 if (--mesh->refct > 0) PetscFunctionReturn(0); 1589 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 1590 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 1591 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 1592 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 1593 ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr); 1594 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 1595 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 1596 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 1597 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 1598 ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 1599 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 1600 ierr = ISDestroy(&mesh->subpointIS);CHKERRQ(ierr); 1601 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 1602 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 1603 ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 1604 ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 1605 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 1606 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 1607 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 1608 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 1609 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 1610 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 1611 ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr); 1612 ierr = PetscFree(mesh->neighbors);CHKERRQ(ierr); 1613 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 1614 ierr = PetscFree(mesh);CHKERRQ(ierr); 1615 PetscFunctionReturn(0); 1616 } 1617 1618 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 1619 { 1620 PetscSection sectionGlobal; 1621 PetscInt bs = -1, mbs; 1622 PetscInt localSize; 1623 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 1624 PetscErrorCode ierr; 1625 MatType mtype; 1626 ISLocalToGlobalMapping ltog; 1627 1628 PetscFunctionBegin; 1629 ierr = MatInitializePackage();CHKERRQ(ierr); 1630 mtype = dm->mattype; 1631 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1632 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 1633 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 1634 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 1635 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1636 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 1637 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 1638 ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr); 1639 if (mbs > 1) bs = mbs; 1640 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 1641 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 1642 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 1643 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 1644 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 1645 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 1646 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 1647 ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr); 1648 if (!isShell) { 1649 PetscSection subSection; 1650 PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 1651 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *ltogidx, lsize; 1652 PetscInt pStart, pEnd, p, dof, cdof; 1653 1654 /* Set localtoglobalmapping on the matrix for MatSetValuesLocal() to work (it also creates the local matrices in case of MATIS) */ 1655 if (isMatIS) { /* need a different l2g map than the one computed by DMGetLocalToGlobalMapping */ 1656 PetscSection section; 1657 PetscInt size; 1658 1659 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 1660 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 1661 ierr = PetscMalloc1(size,<ogidx);CHKERRQ(ierr); 1662 ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr); 1663 } else { 1664 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 1665 } 1666 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1667 for (p = pStart, lsize = 0; p < pEnd; ++p) { 1668 PetscInt bdof; 1669 1670 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 1671 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 1672 dof = dof < 0 ? -(dof+1) : dof; 1673 bdof = cdof && (dof-cdof) ? 1 : dof; 1674 if (dof) { 1675 if (bs < 0) {bs = bdof;} 1676 else if (bs != bdof) {bs = 1; if (!isMatIS) break;} 1677 } 1678 if (isMatIS) { 1679 PetscInt loff,c,off; 1680 ierr = PetscSectionGetOffset(subSection, p, &loff);CHKERRQ(ierr); 1681 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 1682 for (c = 0; c < dof-cdof; ++c, ++lsize) ltogidx[loff+c] = off > -1 ? off+c : -(off+1)+c; 1683 } 1684 } 1685 /* Must have same blocksize on all procs (some might have no points) */ 1686 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 1687 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 1688 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 1689 else {bs = bsMinMax[0];} 1690 bs = PetscMax(1,bs); 1691 if (isMatIS) { /* Must reduce indices by blocksize */ 1692 PetscInt l; 1693 1694 lsize = lsize/bs; 1695 if (bs > 1) for (l = 0; l < lsize; ++l) ltogidx[l] = ltogidx[l*bs]/bs; 1696 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, lsize, ltogidx, PETSC_OWN_POINTER, <og);CHKERRQ(ierr); 1697 } 1698 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 1699 if (isMatIS) { 1700 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 1701 } 1702 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 1703 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1704 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1705 } 1706 ierr = MatSetDM(*J, dm);CHKERRQ(ierr); 1707 PetscFunctionReturn(0); 1708 } 1709 1710 /*@ 1711 DMPlexGetSubdomainSection - Returns the section associated with the subdomain 1712 1713 Not collective 1714 1715 Input Parameter: 1716 . mesh - The DMPlex 1717 1718 Output Parameters: 1719 . subsection - The subdomain section 1720 1721 Level: developer 1722 1723 .seealso: 1724 @*/ 1725 PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 1726 { 1727 DM_Plex *mesh = (DM_Plex*) dm->data; 1728 PetscErrorCode ierr; 1729 1730 PetscFunctionBegin; 1731 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1732 if (!mesh->subdomainSection) { 1733 PetscSection section; 1734 PetscSF sf; 1735 1736 ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr); 1737 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 1738 ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr); 1739 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 1740 } 1741 *subsection = mesh->subdomainSection; 1742 PetscFunctionReturn(0); 1743 } 1744 1745 /*@ 1746 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1747 1748 Not collective 1749 1750 Input Parameter: 1751 . mesh - The DMPlex 1752 1753 Output Parameters: 1754 + pStart - The first mesh point 1755 - pEnd - The upper bound for mesh points 1756 1757 Level: beginner 1758 1759 .seealso: DMPlexCreate(), DMPlexSetChart() 1760 @*/ 1761 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1762 { 1763 DM_Plex *mesh = (DM_Plex*) dm->data; 1764 PetscErrorCode ierr; 1765 1766 PetscFunctionBegin; 1767 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1768 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1769 PetscFunctionReturn(0); 1770 } 1771 1772 /*@ 1773 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1774 1775 Not collective 1776 1777 Input Parameters: 1778 + mesh - The DMPlex 1779 . pStart - The first mesh point 1780 - pEnd - The upper bound for mesh points 1781 1782 Output Parameters: 1783 1784 Level: beginner 1785 1786 .seealso: DMPlexCreate(), DMPlexGetChart() 1787 @*/ 1788 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1789 { 1790 DM_Plex *mesh = (DM_Plex*) dm->data; 1791 PetscErrorCode ierr; 1792 1793 PetscFunctionBegin; 1794 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1795 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1796 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1797 PetscFunctionReturn(0); 1798 } 1799 1800 /*@ 1801 DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 1802 1803 Not collective 1804 1805 Input Parameters: 1806 + mesh - The DMPlex 1807 - p - The point, which must lie in the chart set with DMPlexSetChart() 1808 1809 Output Parameter: 1810 . size - The cone size for point p 1811 1812 Level: beginner 1813 1814 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1815 @*/ 1816 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1817 { 1818 DM_Plex *mesh = (DM_Plex*) dm->data; 1819 PetscErrorCode ierr; 1820 1821 PetscFunctionBegin; 1822 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1823 PetscValidPointer(size, 3); 1824 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1825 PetscFunctionReturn(0); 1826 } 1827 1828 /*@ 1829 DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 1830 1831 Not collective 1832 1833 Input Parameters: 1834 + mesh - The DMPlex 1835 . p - The point, which must lie in the chart set with DMPlexSetChart() 1836 - size - The cone size for point p 1837 1838 Output Parameter: 1839 1840 Note: 1841 This should be called after DMPlexSetChart(). 1842 1843 Level: beginner 1844 1845 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1846 @*/ 1847 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1848 { 1849 DM_Plex *mesh = (DM_Plex*) dm->data; 1850 PetscErrorCode ierr; 1851 1852 PetscFunctionBegin; 1853 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1854 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1855 1856 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1857 PetscFunctionReturn(0); 1858 } 1859 1860 /*@ 1861 DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 1862 1863 Not collective 1864 1865 Input Parameters: 1866 + mesh - The DMPlex 1867 . p - The point, which must lie in the chart set with DMPlexSetChart() 1868 - size - The additional cone size for point p 1869 1870 Output Parameter: 1871 1872 Note: 1873 This should be called after DMPlexSetChart(). 1874 1875 Level: beginner 1876 1877 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 1878 @*/ 1879 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 1880 { 1881 DM_Plex *mesh = (DM_Plex*) dm->data; 1882 PetscInt csize; 1883 PetscErrorCode ierr; 1884 1885 PetscFunctionBegin; 1886 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1887 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1888 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 1889 1890 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 1891 PetscFunctionReturn(0); 1892 } 1893 1894 /*@C 1895 DMPlexGetCone - Return the points on the in-edges for this point in the DAG 1896 1897 Not collective 1898 1899 Input Parameters: 1900 + dm - The DMPlex 1901 - p - The point, which must lie in the chart set with DMPlexSetChart() 1902 1903 Output Parameter: 1904 . cone - An array of points which are on the in-edges for point p 1905 1906 Level: beginner 1907 1908 Fortran Notes: 1909 Since it returns an array, this routine is only available in Fortran 90, and you must 1910 include petsc.h90 in your code. 1911 You must also call DMPlexRestoreCone() after you finish using the returned array. 1912 DMPlexRestoreCone() is not needed/available in C. 1913 1914 .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart() 1915 @*/ 1916 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1917 { 1918 DM_Plex *mesh = (DM_Plex*) dm->data; 1919 PetscInt off; 1920 PetscErrorCode ierr; 1921 1922 PetscFunctionBegin; 1923 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1924 PetscValidPointer(cone, 3); 1925 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1926 *cone = &mesh->cones[off]; 1927 PetscFunctionReturn(0); 1928 } 1929 1930 /*@C 1931 DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 1932 1933 Not collective 1934 1935 Input Parameters: 1936 + dm - The DMPlex 1937 - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 1938 1939 Output Parameter: 1940 + pConesSection - PetscSection describing the layout of pCones 1941 - pCones - An array of points which are on the in-edges for the point set p 1942 1943 Level: intermediate 1944 1945 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart() 1946 @*/ 1947 PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 1948 { 1949 PetscSection cs, newcs; 1950 PetscInt *cones; 1951 PetscInt *newarr=NULL; 1952 PetscInt n; 1953 PetscErrorCode ierr; 1954 1955 PetscFunctionBegin; 1956 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 1957 ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr); 1958 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 1959 if (pConesSection) *pConesSection = newcs; 1960 if (pCones) { 1961 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 1962 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr); 1963 } 1964 PetscFunctionReturn(0); 1965 } 1966 1967 /*@ 1968 DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 1969 1970 Not collective 1971 1972 Input Parameters: 1973 + dm - The DMPlex 1974 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 1975 1976 Output Parameter: 1977 . expandedPoints - An array of vertices recursively expanded from input points 1978 1979 Level: advanced 1980 1981 Notes: 1982 Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 1983 There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 1984 1985 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth() 1986 @*/ 1987 PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 1988 { 1989 IS *expandedPointsAll; 1990 PetscInt depth; 1991 PetscErrorCode ierr; 1992 1993 PetscFunctionBegin; 1994 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1995 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 1996 PetscValidPointer(expandedPoints, 3); 1997 ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 1998 *expandedPoints = expandedPointsAll[0]; 1999 ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]); 2000 ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2001 PetscFunctionReturn(0); 2002 } 2003 2004 /*@ 2005 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). 2006 2007 Not collective 2008 2009 Input Parameters: 2010 + dm - The DMPlex 2011 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2012 2013 Output Parameter: 2014 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2015 . expandedPoints - (optional) An array of index sets with recursively expanded cones 2016 - sections - (optional) An array of sections which describe mappings from points to their cone points 2017 2018 Level: advanced 2019 2020 Notes: 2021 Like DMPlexGetConeTuple() but recursive. 2022 2023 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. 2024 For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2025 2026 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: 2027 (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2028 (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2029 2030 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2031 @*/ 2032 PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2033 { 2034 const PetscInt *arr0=NULL, *cone=NULL; 2035 PetscInt *arr=NULL, *newarr=NULL; 2036 PetscInt d, depth_, i, n, newn, cn, co, start, end; 2037 IS *expandedPoints_; 2038 PetscSection *sections_; 2039 PetscErrorCode ierr; 2040 2041 PetscFunctionBegin; 2042 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2043 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2044 if (depth) PetscValidIntPointer(depth, 3); 2045 if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2046 if (sections) PetscValidPointer(sections, 5); 2047 ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr); 2048 ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr); 2049 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2050 ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr); 2051 ierr = PetscCalloc1(depth_, §ions_);CHKERRQ(ierr); 2052 arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2053 for (d=depth_-1; d>=0; d--) { 2054 ierr = PetscSectionCreate(PETSC_COMM_SELF, §ions_[d]);CHKERRQ(ierr); 2055 ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr); 2056 for (i=0; i<n; i++) { 2057 ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr); 2058 if (arr[i] >= start && arr[i] < end) { 2059 ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr); 2060 ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr); 2061 } else { 2062 ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr); 2063 } 2064 } 2065 ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr); 2066 ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr); 2067 ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr); 2068 for (i=0; i<n; i++) { 2069 ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr); 2070 ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr); 2071 if (cn > 1) { 2072 ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr); 2073 ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr); 2074 } else { 2075 newarr[co] = arr[i]; 2076 } 2077 } 2078 ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr); 2079 arr = newarr; 2080 n = newn; 2081 } 2082 ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr); 2083 *depth = depth_; 2084 if (expandedPoints) *expandedPoints = expandedPoints_; 2085 else { 2086 for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);} 2087 ierr = PetscFree(expandedPoints_);CHKERRQ(ierr); 2088 } 2089 if (sections) *sections = sections_; 2090 else { 2091 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(§ions_[d]);CHKERRQ(ierr);} 2092 ierr = PetscFree(sections_);CHKERRQ(ierr); 2093 } 2094 PetscFunctionReturn(0); 2095 } 2096 2097 /*@ 2098 DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2099 2100 Not collective 2101 2102 Input Parameters: 2103 + dm - The DMPlex 2104 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2105 2106 Output Parameter: 2107 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2108 . expandedPoints - (optional) An array of recursively expanded cones 2109 - sections - (optional) An array of sections which describe mappings from points to their cone points 2110 2111 Level: advanced 2112 2113 Notes: 2114 See DMPlexGetConeRecursive() for details. 2115 2116 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2117 @*/ 2118 PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2119 { 2120 PetscInt d, depth_; 2121 PetscErrorCode ierr; 2122 2123 PetscFunctionBegin; 2124 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2125 if (depth && *depth != depth_) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2126 if (depth) *depth = 0; 2127 if (expandedPoints) { 2128 for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);} 2129 ierr = PetscFree(*expandedPoints);CHKERRQ(ierr); 2130 } 2131 if (sections) { 2132 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);} 2133 ierr = PetscFree(*sections);CHKERRQ(ierr); 2134 } 2135 PetscFunctionReturn(0); 2136 } 2137 2138 /*@ 2139 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 2140 2141 Not collective 2142 2143 Input Parameters: 2144 + mesh - The DMPlex 2145 . p - The point, which must lie in the chart set with DMPlexSetChart() 2146 - cone - An array of points which are on the in-edges for point p 2147 2148 Output Parameter: 2149 2150 Note: 2151 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2152 2153 Developer Note: Why not call this DMPlexSetCover() 2154 2155 Level: beginner 2156 2157 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize() 2158 @*/ 2159 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 2160 { 2161 DM_Plex *mesh = (DM_Plex*) dm->data; 2162 PetscInt pStart, pEnd; 2163 PetscInt dof, off, c; 2164 PetscErrorCode ierr; 2165 2166 PetscFunctionBegin; 2167 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2168 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2169 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2170 if (dof) PetscValidPointer(cone, 3); 2171 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2172 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); 2173 for (c = 0; c < dof; ++c) { 2174 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); 2175 mesh->cones[off+c] = cone[c]; 2176 } 2177 PetscFunctionReturn(0); 2178 } 2179 2180 /*@C 2181 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 2182 2183 Not collective 2184 2185 Input Parameters: 2186 + mesh - The DMPlex 2187 - p - The point, which must lie in the chart set with DMPlexSetChart() 2188 2189 Output Parameter: 2190 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2191 integer giving the prescription for cone traversal. If it is negative, the cone is 2192 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 2193 the index of the cone point on which to start. 2194 2195 Level: beginner 2196 2197 Fortran Notes: 2198 Since it returns an array, this routine is only available in Fortran 90, and you must 2199 include petsc.h90 in your code. 2200 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 2201 DMPlexRestoreConeOrientation() is not needed/available in C. 2202 2203 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 2204 @*/ 2205 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 2206 { 2207 DM_Plex *mesh = (DM_Plex*) dm->data; 2208 PetscInt off; 2209 PetscErrorCode ierr; 2210 2211 PetscFunctionBegin; 2212 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2213 if (PetscDefined(USE_DEBUG)) { 2214 PetscInt dof; 2215 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2216 if (dof) PetscValidPointer(coneOrientation, 3); 2217 } 2218 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2219 2220 *coneOrientation = &mesh->coneOrientations[off]; 2221 PetscFunctionReturn(0); 2222 } 2223 2224 /*@ 2225 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 2226 2227 Not collective 2228 2229 Input Parameters: 2230 + mesh - The DMPlex 2231 . p - The point, which must lie in the chart set with DMPlexSetChart() 2232 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2233 integer giving the prescription for cone traversal. If it is negative, the cone is 2234 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 2235 the index of the cone point on which to start. 2236 2237 Output Parameter: 2238 2239 Note: 2240 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2241 2242 Level: beginner 2243 2244 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2245 @*/ 2246 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 2247 { 2248 DM_Plex *mesh = (DM_Plex*) dm->data; 2249 PetscInt pStart, pEnd; 2250 PetscInt dof, off, c; 2251 PetscErrorCode ierr; 2252 2253 PetscFunctionBegin; 2254 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2255 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2256 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2257 if (dof) PetscValidPointer(coneOrientation, 3); 2258 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2259 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); 2260 for (c = 0; c < dof; ++c) { 2261 PetscInt cdof, o = coneOrientation[c]; 2262 2263 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 2264 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); 2265 mesh->coneOrientations[off+c] = o; 2266 } 2267 PetscFunctionReturn(0); 2268 } 2269 2270 /*@ 2271 DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 2272 2273 Not collective 2274 2275 Input Parameters: 2276 + mesh - The DMPlex 2277 . p - The point, which must lie in the chart set with DMPlexSetChart() 2278 . conePos - The local index in the cone where the point should be put 2279 - conePoint - The mesh point to insert 2280 2281 Level: beginner 2282 2283 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2284 @*/ 2285 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 2286 { 2287 DM_Plex *mesh = (DM_Plex*) dm->data; 2288 PetscInt pStart, pEnd; 2289 PetscInt dof, off; 2290 PetscErrorCode ierr; 2291 2292 PetscFunctionBegin; 2293 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2294 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2295 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); 2296 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); 2297 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2298 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2299 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); 2300 mesh->cones[off+conePos] = conePoint; 2301 PetscFunctionReturn(0); 2302 } 2303 2304 /*@ 2305 DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 2306 2307 Not collective 2308 2309 Input Parameters: 2310 + mesh - The DMPlex 2311 . p - The point, which must lie in the chart set with DMPlexSetChart() 2312 . conePos - The local index in the cone where the point should be put 2313 - coneOrientation - The point orientation to insert 2314 2315 Level: beginner 2316 2317 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2318 @*/ 2319 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 2320 { 2321 DM_Plex *mesh = (DM_Plex*) dm->data; 2322 PetscInt pStart, pEnd; 2323 PetscInt dof, off; 2324 PetscErrorCode ierr; 2325 2326 PetscFunctionBegin; 2327 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2328 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2329 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); 2330 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2331 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2332 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); 2333 mesh->coneOrientations[off+conePos] = coneOrientation; 2334 PetscFunctionReturn(0); 2335 } 2336 2337 /*@ 2338 DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 2339 2340 Not collective 2341 2342 Input Parameters: 2343 + mesh - The DMPlex 2344 - p - The point, which must lie in the chart set with DMPlexSetChart() 2345 2346 Output Parameter: 2347 . size - The support size for point p 2348 2349 Level: beginner 2350 2351 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 2352 @*/ 2353 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 2354 { 2355 DM_Plex *mesh = (DM_Plex*) dm->data; 2356 PetscErrorCode ierr; 2357 2358 PetscFunctionBegin; 2359 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2360 PetscValidPointer(size, 3); 2361 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 2362 PetscFunctionReturn(0); 2363 } 2364 2365 /*@ 2366 DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 2367 2368 Not collective 2369 2370 Input Parameters: 2371 + mesh - The DMPlex 2372 . p - The point, which must lie in the chart set with DMPlexSetChart() 2373 - size - The support size for point p 2374 2375 Output Parameter: 2376 2377 Note: 2378 This should be called after DMPlexSetChart(). 2379 2380 Level: beginner 2381 2382 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 2383 @*/ 2384 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 2385 { 2386 DM_Plex *mesh = (DM_Plex*) dm->data; 2387 PetscErrorCode ierr; 2388 2389 PetscFunctionBegin; 2390 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2391 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 2392 2393 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 2394 PetscFunctionReturn(0); 2395 } 2396 2397 /*@C 2398 DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 2399 2400 Not collective 2401 2402 Input Parameters: 2403 + mesh - The DMPlex 2404 - p - The point, which must lie in the chart set with DMPlexSetChart() 2405 2406 Output Parameter: 2407 . support - An array of points which are on the out-edges for point p 2408 2409 Level: beginner 2410 2411 Fortran Notes: 2412 Since it returns an array, this routine is only available in Fortran 90, and you must 2413 include petsc.h90 in your code. 2414 You must also call DMPlexRestoreSupport() after you finish using the returned array. 2415 DMPlexRestoreSupport() is not needed/available in C. 2416 2417 .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart() 2418 @*/ 2419 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 2420 { 2421 DM_Plex *mesh = (DM_Plex*) dm->data; 2422 PetscInt off; 2423 PetscErrorCode ierr; 2424 2425 PetscFunctionBegin; 2426 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2427 PetscValidPointer(support, 3); 2428 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 2429 *support = &mesh->supports[off]; 2430 PetscFunctionReturn(0); 2431 } 2432 2433 /*@ 2434 DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 2435 2436 Not collective 2437 2438 Input Parameters: 2439 + mesh - The DMPlex 2440 . p - The point, which must lie in the chart set with DMPlexSetChart() 2441 - support - An array of points which are on the out-edges for point p 2442 2443 Output Parameter: 2444 2445 Note: 2446 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 2447 2448 Level: beginner 2449 2450 .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 2451 @*/ 2452 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 2453 { 2454 DM_Plex *mesh = (DM_Plex*) dm->data; 2455 PetscInt pStart, pEnd; 2456 PetscInt dof, off, c; 2457 PetscErrorCode ierr; 2458 2459 PetscFunctionBegin; 2460 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2461 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 2462 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 2463 if (dof) PetscValidPointer(support, 3); 2464 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 2465 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); 2466 for (c = 0; c < dof; ++c) { 2467 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); 2468 mesh->supports[off+c] = support[c]; 2469 } 2470 PetscFunctionReturn(0); 2471 } 2472 2473 /*@ 2474 DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 2475 2476 Not collective 2477 2478 Input Parameters: 2479 + mesh - The DMPlex 2480 . p - The point, which must lie in the chart set with DMPlexSetChart() 2481 . supportPos - The local index in the cone where the point should be put 2482 - supportPoint - The mesh point to insert 2483 2484 Level: beginner 2485 2486 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2487 @*/ 2488 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 2489 { 2490 DM_Plex *mesh = (DM_Plex*) dm->data; 2491 PetscInt pStart, pEnd; 2492 PetscInt dof, off; 2493 PetscErrorCode ierr; 2494 2495 PetscFunctionBegin; 2496 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2497 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 2498 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 2499 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 2500 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); 2501 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); 2502 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); 2503 mesh->supports[off+supportPos] = supportPoint; 2504 PetscFunctionReturn(0); 2505 } 2506 2507 /*@C 2508 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 2509 2510 Not collective 2511 2512 Input Parameters: 2513 + mesh - The DMPlex 2514 . p - The point, which must lie in the chart set with DMPlexSetChart() 2515 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 2516 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 2517 2518 Output Parameters: 2519 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 2520 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 2521 2522 Note: 2523 If using internal storage (points is NULL on input), each call overwrites the last output. 2524 2525 Fortran Notes: 2526 Since it returns an array, this routine is only available in Fortran 90, and you must 2527 include petsc.h90 in your code. 2528 2529 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2530 2531 Level: beginner 2532 2533 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 2534 @*/ 2535 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 2536 { 2537 DM_Plex *mesh = (DM_Plex*) dm->data; 2538 PetscInt *closure, *fifo; 2539 const PetscInt *tmp = NULL, *tmpO = NULL; 2540 PetscInt tmpSize, t; 2541 PetscInt depth = 0, maxSize; 2542 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 2543 PetscErrorCode ierr; 2544 2545 PetscFunctionBegin; 2546 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2547 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2548 /* This is only 1-level */ 2549 if (useCone) { 2550 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 2551 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 2552 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 2553 } else { 2554 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 2555 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 2556 } 2557 if (depth == 1) { 2558 if (*points) { 2559 closure = *points; 2560 } else { 2561 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 2562 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 2563 } 2564 closure[0] = p; closure[1] = 0; 2565 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 2566 closure[closureSize] = tmp[t]; 2567 closure[closureSize+1] = tmpO ? tmpO[t] : 0; 2568 } 2569 if (numPoints) *numPoints = closureSize/2; 2570 if (points) *points = closure; 2571 PetscFunctionReturn(0); 2572 } 2573 { 2574 PetscInt c, coneSeries, s,supportSeries; 2575 2576 c = mesh->maxConeSize; 2577 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 2578 s = mesh->maxSupportSize; 2579 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 2580 maxSize = 2*PetscMax(coneSeries,supportSeries); 2581 } 2582 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 2583 if (*points) { 2584 closure = *points; 2585 } else { 2586 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 2587 } 2588 closure[0] = p; closure[1] = 0; 2589 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 2590 const PetscInt cp = tmp[t]; 2591 const PetscInt co = tmpO ? tmpO[t] : 0; 2592 2593 closure[closureSize] = cp; 2594 closure[closureSize+1] = co; 2595 fifo[fifoSize] = cp; 2596 fifo[fifoSize+1] = co; 2597 } 2598 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 2599 while (fifoSize - fifoStart) { 2600 const PetscInt q = fifo[fifoStart]; 2601 const PetscInt o = fifo[fifoStart+1]; 2602 const PetscInt rev = o >= 0 ? 0 : 1; 2603 const PetscInt off = rev ? -(o+1) : o; 2604 2605 if (useCone) { 2606 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 2607 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 2608 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 2609 } else { 2610 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 2611 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 2612 tmpO = NULL; 2613 } 2614 for (t = 0; t < tmpSize; ++t) { 2615 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 2616 const PetscInt cp = tmp[i]; 2617 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 2618 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 2619 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 2620 PetscInt co = tmpO ? tmpO[i] : 0; 2621 PetscInt c; 2622 2623 if (rev) { 2624 PetscInt childSize, coff; 2625 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 2626 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 2627 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 2628 } 2629 /* Check for duplicate */ 2630 for (c = 0; c < closureSize; c += 2) { 2631 if (closure[c] == cp) break; 2632 } 2633 if (c == closureSize) { 2634 closure[closureSize] = cp; 2635 closure[closureSize+1] = co; 2636 fifo[fifoSize] = cp; 2637 fifo[fifoSize+1] = co; 2638 closureSize += 2; 2639 fifoSize += 2; 2640 } 2641 } 2642 fifoStart += 2; 2643 } 2644 if (numPoints) *numPoints = closureSize/2; 2645 if (points) *points = closure; 2646 ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 2647 PetscFunctionReturn(0); 2648 } 2649 2650 /*@C 2651 DMPlexGetTransitiveClosure_Internal - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG with a specified initial orientation 2652 2653 Not collective 2654 2655 Input Parameters: 2656 + mesh - The DMPlex 2657 . p - The point, which must lie in the chart set with DMPlexSetChart() 2658 . orientation - The orientation of the point 2659 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 2660 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 2661 2662 Output Parameters: 2663 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 2664 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 2665 2666 Note: 2667 If using internal storage (points is NULL on input), each call overwrites the last output. 2668 2669 Fortran Notes: 2670 Since it returns an array, this routine is only available in Fortran 90, and you must 2671 include petsc.h90 in your code. 2672 2673 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2674 2675 Level: beginner 2676 2677 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 2678 @*/ 2679 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 2680 { 2681 DM_Plex *mesh = (DM_Plex*) dm->data; 2682 PetscInt *closure, *fifo; 2683 const PetscInt *tmp = NULL, *tmpO = NULL; 2684 PetscInt tmpSize, t; 2685 PetscInt depth = 0, maxSize; 2686 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 2687 PetscErrorCode ierr; 2688 2689 PetscFunctionBegin; 2690 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2691 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2692 /* This is only 1-level */ 2693 if (useCone) { 2694 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 2695 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 2696 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 2697 } else { 2698 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 2699 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 2700 } 2701 if (depth == 1) { 2702 if (*points) { 2703 closure = *points; 2704 } else { 2705 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 2706 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 2707 } 2708 closure[0] = p; closure[1] = ornt; 2709 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 2710 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 2711 closure[closureSize] = tmp[i]; 2712 closure[closureSize+1] = tmpO ? tmpO[i] : 0; 2713 } 2714 if (numPoints) *numPoints = closureSize/2; 2715 if (points) *points = closure; 2716 PetscFunctionReturn(0); 2717 } 2718 { 2719 PetscInt c, coneSeries, s,supportSeries; 2720 2721 c = mesh->maxConeSize; 2722 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 2723 s = mesh->maxSupportSize; 2724 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 2725 maxSize = 2*PetscMax(coneSeries,supportSeries); 2726 } 2727 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 2728 if (*points) { 2729 closure = *points; 2730 } else { 2731 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 2732 } 2733 closure[0] = p; closure[1] = ornt; 2734 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 2735 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 2736 const PetscInt cp = tmp[i]; 2737 PetscInt co = tmpO ? tmpO[i] : 0; 2738 2739 if (ornt < 0) { 2740 PetscInt childSize, coff; 2741 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 2742 coff = co < 0 ? -(tmpO[i]+1) : tmpO[i]; 2743 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 2744 } 2745 closure[closureSize] = cp; 2746 closure[closureSize+1] = co; 2747 fifo[fifoSize] = cp; 2748 fifo[fifoSize+1] = co; 2749 } 2750 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 2751 while (fifoSize - fifoStart) { 2752 const PetscInt q = fifo[fifoStart]; 2753 const PetscInt o = fifo[fifoStart+1]; 2754 const PetscInt rev = o >= 0 ? 0 : 1; 2755 const PetscInt off = rev ? -(o+1) : o; 2756 2757 if (useCone) { 2758 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 2759 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 2760 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 2761 } else { 2762 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 2763 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 2764 tmpO = NULL; 2765 } 2766 for (t = 0; t < tmpSize; ++t) { 2767 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 2768 const PetscInt cp = tmp[i]; 2769 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 2770 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 2771 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 2772 PetscInt co = tmpO ? tmpO[i] : 0; 2773 PetscInt c; 2774 2775 if (rev) { 2776 PetscInt childSize, coff; 2777 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 2778 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 2779 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 2780 } 2781 /* Check for duplicate */ 2782 for (c = 0; c < closureSize; c += 2) { 2783 if (closure[c] == cp) break; 2784 } 2785 if (c == closureSize) { 2786 closure[closureSize] = cp; 2787 closure[closureSize+1] = co; 2788 fifo[fifoSize] = cp; 2789 fifo[fifoSize+1] = co; 2790 closureSize += 2; 2791 fifoSize += 2; 2792 } 2793 } 2794 fifoStart += 2; 2795 } 2796 if (numPoints) *numPoints = closureSize/2; 2797 if (points) *points = closure; 2798 ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 2799 PetscFunctionReturn(0); 2800 } 2801 2802 /*@C 2803 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 2804 2805 Not collective 2806 2807 Input Parameters: 2808 + mesh - The DMPlex 2809 . p - The point, which must lie in the chart set with DMPlexSetChart() 2810 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 2811 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints, zeroed on exit 2812 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...], zeroed on exit 2813 2814 Note: 2815 If not using internal storage (points is not NULL on input), this call is unnecessary 2816 2817 Fortran Notes: 2818 Since it returns an array, this routine is only available in Fortran 90, and you must 2819 include petsc.h90 in your code. 2820 2821 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2822 2823 Level: beginner 2824 2825 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 2826 @*/ 2827 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 2828 { 2829 PetscErrorCode ierr; 2830 2831 PetscFunctionBegin; 2832 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2833 if (numPoints) PetscValidIntPointer(numPoints,4); 2834 if (points) PetscValidPointer(points,5); 2835 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr); 2836 if (numPoints) *numPoints = 0; 2837 PetscFunctionReturn(0); 2838 } 2839 2840 /*@ 2841 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 2842 2843 Not collective 2844 2845 Input Parameter: 2846 . mesh - The DMPlex 2847 2848 Output Parameters: 2849 + maxConeSize - The maximum number of in-edges 2850 - maxSupportSize - The maximum number of out-edges 2851 2852 Level: beginner 2853 2854 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2855 @*/ 2856 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 2857 { 2858 DM_Plex *mesh = (DM_Plex*) dm->data; 2859 2860 PetscFunctionBegin; 2861 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2862 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 2863 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 2864 PetscFunctionReturn(0); 2865 } 2866 2867 PetscErrorCode DMSetUp_Plex(DM dm) 2868 { 2869 DM_Plex *mesh = (DM_Plex*) dm->data; 2870 PetscInt size; 2871 PetscErrorCode ierr; 2872 2873 PetscFunctionBegin; 2874 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2875 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 2876 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 2877 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 2878 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 2879 ierr = PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt));CHKERRQ(ierr); 2880 if (mesh->maxSupportSize) { 2881 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 2882 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 2883 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 2884 ierr = PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt));CHKERRQ(ierr); 2885 } 2886 PetscFunctionReturn(0); 2887 } 2888 2889 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 2890 { 2891 PetscErrorCode ierr; 2892 2893 PetscFunctionBegin; 2894 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 2895 ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 2896 if (subdm) {(*subdm)->useNatural = dm->useNatural;} 2897 if (dm->useNatural && dm->sfMigration) { 2898 PetscSF sfMigrationInv,sfNatural; 2899 PetscSection section, sectionSeq; 2900 2901 (*subdm)->sfMigration = dm->sfMigration; 2902 ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr); 2903 ierr = DMGetLocalSection((*subdm), §ion);CHKERRQ(ierr); 2904 ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 2905 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq);CHKERRQ(ierr); 2906 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 2907 2908 ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 2909 (*subdm)->sfNatural = sfNatural; 2910 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 2911 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 2912 } 2913 PetscFunctionReturn(0); 2914 } 2915 2916 PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 2917 { 2918 PetscErrorCode ierr; 2919 PetscInt i = 0; 2920 2921 PetscFunctionBegin; 2922 ierr = DMClone(dms[0], superdm);CHKERRQ(ierr); 2923 ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr); 2924 (*superdm)->useNatural = PETSC_FALSE; 2925 for (i = 0; i < len; i++){ 2926 if (dms[i]->useNatural && dms[i]->sfMigration) { 2927 PetscSF sfMigrationInv,sfNatural; 2928 PetscSection section, sectionSeq; 2929 2930 (*superdm)->sfMigration = dms[i]->sfMigration; 2931 ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr); 2932 (*superdm)->useNatural = PETSC_TRUE; 2933 ierr = DMGetLocalSection((*superdm), §ion);CHKERRQ(ierr); 2934 ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 2935 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq);CHKERRQ(ierr); 2936 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 2937 2938 ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 2939 (*superdm)->sfNatural = sfNatural; 2940 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 2941 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 2942 break; 2943 } 2944 } 2945 PetscFunctionReturn(0); 2946 } 2947 2948 /*@ 2949 DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 2950 2951 Not collective 2952 2953 Input Parameter: 2954 . mesh - The DMPlex 2955 2956 Output Parameter: 2957 2958 Note: 2959 This should be called after all calls to DMPlexSetCone() 2960 2961 Level: beginner 2962 2963 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 2964 @*/ 2965 PetscErrorCode DMPlexSymmetrize(DM dm) 2966 { 2967 DM_Plex *mesh = (DM_Plex*) dm->data; 2968 PetscInt *offsets; 2969 PetscInt supportSize; 2970 PetscInt pStart, pEnd, p; 2971 PetscErrorCode ierr; 2972 2973 PetscFunctionBegin; 2974 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2975 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 2976 ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 2977 /* Calculate support sizes */ 2978 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2979 for (p = pStart; p < pEnd; ++p) { 2980 PetscInt dof, off, c; 2981 2982 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2983 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2984 for (c = off; c < off+dof; ++c) { 2985 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 2986 } 2987 } 2988 for (p = pStart; p < pEnd; ++p) { 2989 PetscInt dof; 2990 2991 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 2992 2993 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 2994 } 2995 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 2996 /* Calculate supports */ 2997 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 2998 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 2999 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 3000 for (p = pStart; p < pEnd; ++p) { 3001 PetscInt dof, off, c; 3002 3003 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3004 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3005 for (c = off; c < off+dof; ++c) { 3006 const PetscInt q = mesh->cones[c]; 3007 PetscInt offS; 3008 3009 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 3010 3011 mesh->supports[offS+offsets[q]] = p; 3012 ++offsets[q]; 3013 } 3014 } 3015 ierr = PetscFree(offsets);CHKERRQ(ierr); 3016 ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3017 PetscFunctionReturn(0); 3018 } 3019 3020 static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3021 { 3022 IS stratumIS; 3023 PetscErrorCode ierr; 3024 3025 PetscFunctionBegin; 3026 if (pStart >= pEnd) PetscFunctionReturn(0); 3027 if (PetscDefined(USE_DEBUG)) { 3028 PetscInt qStart, qEnd, numLevels, level; 3029 PetscBool overlap = PETSC_FALSE; 3030 ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr); 3031 for (level = 0; level < numLevels; level++) { 3032 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3033 if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3034 } 3035 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); 3036 } 3037 ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr); 3038 ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr); 3039 ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 3040 PetscFunctionReturn(0); 3041 } 3042 3043 /*@ 3044 DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 3045 can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3046 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3047 the DAG. 3048 3049 Collective on dm 3050 3051 Input Parameter: 3052 . mesh - The DMPlex 3053 3054 Output Parameter: 3055 3056 Notes: 3057 Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3058 meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 3059 until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3060 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3061 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3062 3063 The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3064 if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3065 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 3066 to interpolate only that one (e0), so that 3067 $ cone(c0) = {e0, v2} 3068 $ cone(e0) = {v0, v1} 3069 If DMPlexStratify() is run on this mesh, it will give depths 3070 $ depth 0 = {v0, v1, v2} 3071 $ depth 1 = {e0, c0} 3072 where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3073 3074 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3075 3076 Level: beginner 3077 3078 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes() 3079 @*/ 3080 PetscErrorCode DMPlexStratify(DM dm) 3081 { 3082 DM_Plex *mesh = (DM_Plex*) dm->data; 3083 DMLabel label; 3084 PetscInt pStart, pEnd, p; 3085 PetscInt numRoots = 0, numLeaves = 0; 3086 PetscErrorCode ierr; 3087 3088 PetscFunctionBegin; 3089 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3090 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3091 3092 /* Create depth label */ 3093 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3094 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 3095 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3096 3097 { 3098 /* Initialize roots and count leaves */ 3099 PetscInt sMin = PETSC_MAX_INT; 3100 PetscInt sMax = PETSC_MIN_INT; 3101 PetscInt coneSize, supportSize; 3102 3103 for (p = pStart; p < pEnd; ++p) { 3104 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3105 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3106 if (!coneSize && supportSize) { 3107 sMin = PetscMin(p, sMin); 3108 sMax = PetscMax(p, sMax); 3109 ++numRoots; 3110 } else if (!supportSize && coneSize) { 3111 ++numLeaves; 3112 } else if (!supportSize && !coneSize) { 3113 /* Isolated points */ 3114 sMin = PetscMin(p, sMin); 3115 sMax = PetscMax(p, sMax); 3116 } 3117 } 3118 ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr); 3119 } 3120 3121 if (numRoots + numLeaves == (pEnd - pStart)) { 3122 PetscInt sMin = PETSC_MAX_INT; 3123 PetscInt sMax = PETSC_MIN_INT; 3124 PetscInt coneSize, supportSize; 3125 3126 for (p = pStart; p < pEnd; ++p) { 3127 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3128 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3129 if (!supportSize && coneSize) { 3130 sMin = PetscMin(p, sMin); 3131 sMax = PetscMax(p, sMax); 3132 } 3133 } 3134 ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr); 3135 } else { 3136 PetscInt level = 0; 3137 PetscInt qStart, qEnd, q; 3138 3139 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3140 while (qEnd > qStart) { 3141 PetscInt sMin = PETSC_MAX_INT; 3142 PetscInt sMax = PETSC_MIN_INT; 3143 3144 for (q = qStart; q < qEnd; ++q) { 3145 const PetscInt *support; 3146 PetscInt supportSize, s; 3147 3148 ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr); 3149 ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr); 3150 for (s = 0; s < supportSize; ++s) { 3151 sMin = PetscMin(support[s], sMin); 3152 sMax = PetscMax(support[s], sMax); 3153 } 3154 } 3155 ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr); 3156 ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr); 3157 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3158 } 3159 } 3160 { /* just in case there is an empty process */ 3161 PetscInt numValues, maxValues = 0, v; 3162 3163 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 3164 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 3165 for (v = numValues; v < maxValues; v++) { 3166 ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr); 3167 } 3168 } 3169 ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr); 3170 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3171 PetscFunctionReturn(0); 3172 } 3173 3174 PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 3175 { 3176 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3177 PetscInt dim, depth, pheight, coneSize; 3178 PetscErrorCode ierr; 3179 3180 PetscFunctionBeginHot; 3181 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3182 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3183 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3184 pheight = depth - pdepth; 3185 if (depth <= 1) { 3186 switch (pdepth) { 3187 case 0: ct = DM_POLYTOPE_POINT;break; 3188 case 1: 3189 switch (coneSize) { 3190 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3191 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3192 case 4: 3193 switch (dim) { 3194 case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 3195 case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 3196 default: break; 3197 } 3198 break; 3199 case 5: ct = DM_POLYTOPE_PYRAMID;break; 3200 case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3201 case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 3202 default: break; 3203 } 3204 } 3205 } else { 3206 if (pdepth == 0) { 3207 ct = DM_POLYTOPE_POINT; 3208 } else if (pheight == 0) { 3209 switch (dim) { 3210 case 1: 3211 switch (coneSize) { 3212 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3213 default: break; 3214 } 3215 break; 3216 case 2: 3217 switch (coneSize) { 3218 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3219 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3220 default: break; 3221 } 3222 break; 3223 case 3: 3224 switch (coneSize) { 3225 case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 3226 case 5: 3227 { 3228 const PetscInt *cone; 3229 PetscInt faceConeSize; 3230 3231 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 3232 ierr = DMPlexGetConeSize(dm, cone[0], &faceConeSize);CHKERRQ(ierr); 3233 switch (faceConeSize) { 3234 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3235 case 4: ct = DM_POLYTOPE_PYRAMID;break; 3236 } 3237 } 3238 break; 3239 case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 3240 default: break; 3241 } 3242 break; 3243 default: break; 3244 } 3245 } else if (pheight > 0) { 3246 switch (coneSize) { 3247 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3248 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3249 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3250 default: break; 3251 } 3252 } 3253 } 3254 *pt = ct; 3255 PetscFunctionReturn(0); 3256 } 3257 3258 /*@ 3259 DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 3260 3261 Collective on dm 3262 3263 Input Parameter: 3264 . mesh - The DMPlex 3265 3266 DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 3267 3268 Level: developer 3269 3270 Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 3271 internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 3272 automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 3273 3274 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel() 3275 @*/ 3276 PetscErrorCode DMPlexComputeCellTypes(DM dm) 3277 { 3278 DM_Plex *mesh; 3279 DMLabel ctLabel; 3280 PetscInt pStart, pEnd, p; 3281 PetscErrorCode ierr; 3282 3283 PetscFunctionBegin; 3284 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3285 mesh = (DM_Plex *) dm->data; 3286 ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr); 3287 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 3288 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3289 for (p = pStart; p < pEnd; ++p) { 3290 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3291 PetscInt pdepth; 3292 3293 ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr); 3294 ierr = DMPlexComputeCellType_Internal(dm, p, pdepth, &ct);CHKERRQ(ierr); 3295 if (ct == DM_POLYTOPE_UNKNOWN) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p); 3296 ierr = DMLabelSetValue(ctLabel, p, ct);CHKERRQ(ierr); 3297 } 3298 ierr = PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState);CHKERRQ(ierr); 3299 ierr = PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr); 3300 PetscFunctionReturn(0); 3301 } 3302 3303 /*@C 3304 DMPlexGetJoin - Get an array for the join of the set of points 3305 3306 Not Collective 3307 3308 Input Parameters: 3309 + dm - The DMPlex object 3310 . numPoints - The number of input points for the join 3311 - points - The input points 3312 3313 Output Parameters: 3314 + numCoveredPoints - The number of points in the join 3315 - coveredPoints - The points in the join 3316 3317 Level: intermediate 3318 3319 Note: Currently, this is restricted to a single level join 3320 3321 Fortran Notes: 3322 Since it returns an array, this routine is only available in Fortran 90, and you must 3323 include petsc.h90 in your code. 3324 3325 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3326 3327 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 3328 @*/ 3329 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3330 { 3331 DM_Plex *mesh = (DM_Plex*) dm->data; 3332 PetscInt *join[2]; 3333 PetscInt joinSize, i = 0; 3334 PetscInt dof, off, p, c, m; 3335 PetscErrorCode ierr; 3336 3337 PetscFunctionBegin; 3338 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3339 PetscValidIntPointer(points, 3); 3340 PetscValidIntPointer(numCoveredPoints, 4); 3341 PetscValidPointer(coveredPoints, 5); 3342 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 3343 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 3344 /* Copy in support of first point */ 3345 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 3346 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 3347 for (joinSize = 0; joinSize < dof; ++joinSize) { 3348 join[i][joinSize] = mesh->supports[off+joinSize]; 3349 } 3350 /* Check each successive support */ 3351 for (p = 1; p < numPoints; ++p) { 3352 PetscInt newJoinSize = 0; 3353 3354 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 3355 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 3356 for (c = 0; c < dof; ++c) { 3357 const PetscInt point = mesh->supports[off+c]; 3358 3359 for (m = 0; m < joinSize; ++m) { 3360 if (point == join[i][m]) { 3361 join[1-i][newJoinSize++] = point; 3362 break; 3363 } 3364 } 3365 } 3366 joinSize = newJoinSize; 3367 i = 1-i; 3368 } 3369 *numCoveredPoints = joinSize; 3370 *coveredPoints = join[i]; 3371 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 3372 PetscFunctionReturn(0); 3373 } 3374 3375 /*@C 3376 DMPlexRestoreJoin - Restore an array for the join of the set of points 3377 3378 Not Collective 3379 3380 Input Parameters: 3381 + dm - The DMPlex object 3382 . numPoints - The number of input points for the join 3383 - points - The input points 3384 3385 Output Parameters: 3386 + numCoveredPoints - The number of points in the join 3387 - coveredPoints - The points in the join 3388 3389 Fortran Notes: 3390 Since it returns an array, this routine is only available in Fortran 90, and you must 3391 include petsc.h90 in your code. 3392 3393 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3394 3395 Level: intermediate 3396 3397 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 3398 @*/ 3399 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3400 { 3401 PetscErrorCode ierr; 3402 3403 PetscFunctionBegin; 3404 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3405 if (points) PetscValidIntPointer(points,3); 3406 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 3407 PetscValidPointer(coveredPoints, 5); 3408 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 3409 if (numCoveredPoints) *numCoveredPoints = 0; 3410 PetscFunctionReturn(0); 3411 } 3412 3413 /*@C 3414 DMPlexGetFullJoin - Get an array for the join of the set of points 3415 3416 Not Collective 3417 3418 Input Parameters: 3419 + dm - The DMPlex object 3420 . numPoints - The number of input points for the join 3421 - points - The input points 3422 3423 Output Parameters: 3424 + numCoveredPoints - The number of points in the join 3425 - coveredPoints - The points in the join 3426 3427 Fortran Notes: 3428 Since it returns an array, this routine is only available in Fortran 90, and you must 3429 include petsc.h90 in your code. 3430 3431 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3432 3433 Level: intermediate 3434 3435 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 3436 @*/ 3437 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3438 { 3439 DM_Plex *mesh = (DM_Plex*) dm->data; 3440 PetscInt *offsets, **closures; 3441 PetscInt *join[2]; 3442 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 3443 PetscInt p, d, c, m, ms; 3444 PetscErrorCode ierr; 3445 3446 PetscFunctionBegin; 3447 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3448 PetscValidIntPointer(points, 3); 3449 PetscValidIntPointer(numCoveredPoints, 4); 3450 PetscValidPointer(coveredPoints, 5); 3451 3452 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3453 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 3454 ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 3455 ms = mesh->maxSupportSize; 3456 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 3457 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 3458 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 3459 3460 for (p = 0; p < numPoints; ++p) { 3461 PetscInt closureSize; 3462 3463 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 3464 3465 offsets[p*(depth+2)+0] = 0; 3466 for (d = 0; d < depth+1; ++d) { 3467 PetscInt pStart, pEnd, i; 3468 3469 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3470 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 3471 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 3472 offsets[p*(depth+2)+d+1] = i; 3473 break; 3474 } 3475 } 3476 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 3477 } 3478 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); 3479 } 3480 for (d = 0; d < depth+1; ++d) { 3481 PetscInt dof; 3482 3483 /* Copy in support of first point */ 3484 dof = offsets[d+1] - offsets[d]; 3485 for (joinSize = 0; joinSize < dof; ++joinSize) { 3486 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 3487 } 3488 /* Check each successive cone */ 3489 for (p = 1; p < numPoints && joinSize; ++p) { 3490 PetscInt newJoinSize = 0; 3491 3492 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 3493 for (c = 0; c < dof; ++c) { 3494 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 3495 3496 for (m = 0; m < joinSize; ++m) { 3497 if (point == join[i][m]) { 3498 join[1-i][newJoinSize++] = point; 3499 break; 3500 } 3501 } 3502 } 3503 joinSize = newJoinSize; 3504 i = 1-i; 3505 } 3506 if (joinSize) break; 3507 } 3508 *numCoveredPoints = joinSize; 3509 *coveredPoints = join[i]; 3510 for (p = 0; p < numPoints; ++p) { 3511 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 3512 } 3513 ierr = PetscFree(closures);CHKERRQ(ierr); 3514 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 3515 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 3516 PetscFunctionReturn(0); 3517 } 3518 3519 /*@C 3520 DMPlexGetMeet - Get an array for the meet of the set of points 3521 3522 Not Collective 3523 3524 Input Parameters: 3525 + dm - The DMPlex object 3526 . numPoints - The number of input points for the meet 3527 - points - The input points 3528 3529 Output Parameters: 3530 + numCoveredPoints - The number of points in the meet 3531 - coveredPoints - The points in the meet 3532 3533 Level: intermediate 3534 3535 Note: Currently, this is restricted to a single level meet 3536 3537 Fortran Notes: 3538 Since it returns an array, this routine is only available in Fortran 90, and you must 3539 include petsc.h90 in your code. 3540 3541 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3542 3543 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 3544 @*/ 3545 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 3546 { 3547 DM_Plex *mesh = (DM_Plex*) dm->data; 3548 PetscInt *meet[2]; 3549 PetscInt meetSize, i = 0; 3550 PetscInt dof, off, p, c, m; 3551 PetscErrorCode ierr; 3552 3553 PetscFunctionBegin; 3554 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3555 PetscValidPointer(points, 3); 3556 PetscValidPointer(numCoveringPoints, 4); 3557 PetscValidPointer(coveringPoints, 5); 3558 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 3559 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 3560 /* Copy in cone of first point */ 3561 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 3562 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 3563 for (meetSize = 0; meetSize < dof; ++meetSize) { 3564 meet[i][meetSize] = mesh->cones[off+meetSize]; 3565 } 3566 /* Check each successive cone */ 3567 for (p = 1; p < numPoints; ++p) { 3568 PetscInt newMeetSize = 0; 3569 3570 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 3571 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 3572 for (c = 0; c < dof; ++c) { 3573 const PetscInt point = mesh->cones[off+c]; 3574 3575 for (m = 0; m < meetSize; ++m) { 3576 if (point == meet[i][m]) { 3577 meet[1-i][newMeetSize++] = point; 3578 break; 3579 } 3580 } 3581 } 3582 meetSize = newMeetSize; 3583 i = 1-i; 3584 } 3585 *numCoveringPoints = meetSize; 3586 *coveringPoints = meet[i]; 3587 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 3588 PetscFunctionReturn(0); 3589 } 3590 3591 /*@C 3592 DMPlexRestoreMeet - Restore an array for the meet of the set of points 3593 3594 Not Collective 3595 3596 Input Parameters: 3597 + dm - The DMPlex object 3598 . numPoints - The number of input points for the meet 3599 - points - The input points 3600 3601 Output Parameters: 3602 + numCoveredPoints - The number of points in the meet 3603 - coveredPoints - The points in the meet 3604 3605 Level: intermediate 3606 3607 Fortran Notes: 3608 Since it returns an array, this routine is only available in Fortran 90, and you must 3609 include petsc.h90 in your code. 3610 3611 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3612 3613 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 3614 @*/ 3615 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3616 { 3617 PetscErrorCode ierr; 3618 3619 PetscFunctionBegin; 3620 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3621 if (points) PetscValidIntPointer(points,3); 3622 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 3623 PetscValidPointer(coveredPoints,5); 3624 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 3625 if (numCoveredPoints) *numCoveredPoints = 0; 3626 PetscFunctionReturn(0); 3627 } 3628 3629 /*@C 3630 DMPlexGetFullMeet - Get an array for the meet of the set of points 3631 3632 Not Collective 3633 3634 Input Parameters: 3635 + dm - The DMPlex object 3636 . numPoints - The number of input points for the meet 3637 - points - The input points 3638 3639 Output Parameters: 3640 + numCoveredPoints - The number of points in the meet 3641 - coveredPoints - The points in the meet 3642 3643 Level: intermediate 3644 3645 Fortran Notes: 3646 Since it returns an array, this routine is only available in Fortran 90, and you must 3647 include petsc.h90 in your code. 3648 3649 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3650 3651 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 3652 @*/ 3653 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3654 { 3655 DM_Plex *mesh = (DM_Plex*) dm->data; 3656 PetscInt *offsets, **closures; 3657 PetscInt *meet[2]; 3658 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 3659 PetscInt p, h, c, m, mc; 3660 PetscErrorCode ierr; 3661 3662 PetscFunctionBegin; 3663 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3664 PetscValidPointer(points, 3); 3665 PetscValidPointer(numCoveredPoints, 4); 3666 PetscValidPointer(coveredPoints, 5); 3667 3668 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 3669 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 3670 ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 3671 mc = mesh->maxConeSize; 3672 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 3673 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 3674 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 3675 3676 for (p = 0; p < numPoints; ++p) { 3677 PetscInt closureSize; 3678 3679 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 3680 3681 offsets[p*(height+2)+0] = 0; 3682 for (h = 0; h < height+1; ++h) { 3683 PetscInt pStart, pEnd, i; 3684 3685 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 3686 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 3687 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 3688 offsets[p*(height+2)+h+1] = i; 3689 break; 3690 } 3691 } 3692 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 3693 } 3694 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); 3695 } 3696 for (h = 0; h < height+1; ++h) { 3697 PetscInt dof; 3698 3699 /* Copy in cone of first point */ 3700 dof = offsets[h+1] - offsets[h]; 3701 for (meetSize = 0; meetSize < dof; ++meetSize) { 3702 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 3703 } 3704 /* Check each successive cone */ 3705 for (p = 1; p < numPoints && meetSize; ++p) { 3706 PetscInt newMeetSize = 0; 3707 3708 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 3709 for (c = 0; c < dof; ++c) { 3710 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 3711 3712 for (m = 0; m < meetSize; ++m) { 3713 if (point == meet[i][m]) { 3714 meet[1-i][newMeetSize++] = point; 3715 break; 3716 } 3717 } 3718 } 3719 meetSize = newMeetSize; 3720 i = 1-i; 3721 } 3722 if (meetSize) break; 3723 } 3724 *numCoveredPoints = meetSize; 3725 *coveredPoints = meet[i]; 3726 for (p = 0; p < numPoints; ++p) { 3727 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 3728 } 3729 ierr = PetscFree(closures);CHKERRQ(ierr); 3730 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 3731 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 3732 PetscFunctionReturn(0); 3733 } 3734 3735 /*@C 3736 DMPlexEqual - Determine if two DMs have the same topology 3737 3738 Not Collective 3739 3740 Input Parameters: 3741 + dmA - A DMPlex object 3742 - dmB - A DMPlex object 3743 3744 Output Parameters: 3745 . equal - PETSC_TRUE if the topologies are identical 3746 3747 Level: intermediate 3748 3749 Notes: 3750 We are not solving graph isomorphism, so we do not permutation. 3751 3752 .seealso: DMPlexGetCone() 3753 @*/ 3754 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 3755 { 3756 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 3757 PetscErrorCode ierr; 3758 3759 PetscFunctionBegin; 3760 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 3761 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 3762 PetscValidPointer(equal, 3); 3763 3764 *equal = PETSC_FALSE; 3765 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 3766 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 3767 if (depth != depthB) PetscFunctionReturn(0); 3768 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 3769 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 3770 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 3771 for (p = pStart; p < pEnd; ++p) { 3772 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 3773 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 3774 3775 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 3776 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 3777 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 3778 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 3779 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 3780 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 3781 if (coneSize != coneSizeB) PetscFunctionReturn(0); 3782 for (c = 0; c < coneSize; ++c) { 3783 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 3784 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 3785 } 3786 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 3787 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 3788 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 3789 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 3790 if (supportSize != supportSizeB) PetscFunctionReturn(0); 3791 for (s = 0; s < supportSize; ++s) { 3792 if (support[s] != supportB[s]) PetscFunctionReturn(0); 3793 } 3794 } 3795 *equal = PETSC_TRUE; 3796 PetscFunctionReturn(0); 3797 } 3798 3799 /*@C 3800 DMPlexGetNumFaceVertices - Returns the number of vertices on a face 3801 3802 Not Collective 3803 3804 Input Parameters: 3805 + dm - The DMPlex 3806 . cellDim - The cell dimension 3807 - numCorners - The number of vertices on a cell 3808 3809 Output Parameters: 3810 . numFaceVertices - The number of vertices on a face 3811 3812 Level: developer 3813 3814 Notes: 3815 Of course this can only work for a restricted set of symmetric shapes 3816 3817 .seealso: DMPlexGetCone() 3818 @*/ 3819 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 3820 { 3821 MPI_Comm comm; 3822 PetscErrorCode ierr; 3823 3824 PetscFunctionBegin; 3825 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3826 PetscValidPointer(numFaceVertices,4); 3827 switch (cellDim) { 3828 case 0: 3829 *numFaceVertices = 0; 3830 break; 3831 case 1: 3832 *numFaceVertices = 1; 3833 break; 3834 case 2: 3835 switch (numCorners) { 3836 case 3: /* triangle */ 3837 *numFaceVertices = 2; /* Edge has 2 vertices */ 3838 break; 3839 case 4: /* quadrilateral */ 3840 *numFaceVertices = 2; /* Edge has 2 vertices */ 3841 break; 3842 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 3843 *numFaceVertices = 3; /* Edge has 3 vertices */ 3844 break; 3845 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 3846 *numFaceVertices = 3; /* Edge has 3 vertices */ 3847 break; 3848 default: 3849 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 3850 } 3851 break; 3852 case 3: 3853 switch (numCorners) { 3854 case 4: /* tetradehdron */ 3855 *numFaceVertices = 3; /* Face has 3 vertices */ 3856 break; 3857 case 6: /* tet cohesive cells */ 3858 *numFaceVertices = 4; /* Face has 4 vertices */ 3859 break; 3860 case 8: /* hexahedron */ 3861 *numFaceVertices = 4; /* Face has 4 vertices */ 3862 break; 3863 case 9: /* tet cohesive Lagrange cells */ 3864 *numFaceVertices = 6; /* Face has 6 vertices */ 3865 break; 3866 case 10: /* quadratic tetrahedron */ 3867 *numFaceVertices = 6; /* Face has 6 vertices */ 3868 break; 3869 case 12: /* hex cohesive Lagrange cells */ 3870 *numFaceVertices = 6; /* Face has 6 vertices */ 3871 break; 3872 case 18: /* quadratic tet cohesive Lagrange cells */ 3873 *numFaceVertices = 6; /* Face has 6 vertices */ 3874 break; 3875 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 3876 *numFaceVertices = 9; /* Face has 9 vertices */ 3877 break; 3878 default: 3879 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 3880 } 3881 break; 3882 default: 3883 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 3884 } 3885 PetscFunctionReturn(0); 3886 } 3887 3888 /*@ 3889 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 3890 3891 Not Collective 3892 3893 Input Parameter: 3894 . dm - The DMPlex object 3895 3896 Output Parameter: 3897 . depthLabel - The DMLabel recording point depth 3898 3899 Level: developer 3900 3901 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), 3902 @*/ 3903 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 3904 { 3905 PetscFunctionBegin; 3906 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3907 PetscValidPointer(depthLabel, 2); 3908 *depthLabel = dm->depthLabel; 3909 PetscFunctionReturn(0); 3910 } 3911 3912 /*@ 3913 DMPlexGetDepth - Get the depth of the DAG representing this mesh 3914 3915 Not Collective 3916 3917 Input Parameter: 3918 . dm - The DMPlex object 3919 3920 Output Parameter: 3921 . depth - The number of strata (breadth first levels) in the DAG 3922 3923 Level: developer 3924 3925 Notes: 3926 This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 3927 The point depth is described more in detail in DMPlexGetDepthStratum(). 3928 An empty mesh gives -1. 3929 3930 .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize() 3931 @*/ 3932 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 3933 { 3934 DMLabel label; 3935 PetscInt d = 0; 3936 PetscErrorCode ierr; 3937 3938 PetscFunctionBegin; 3939 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3940 PetscValidPointer(depth, 2); 3941 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3942 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 3943 *depth = d-1; 3944 PetscFunctionReturn(0); 3945 } 3946 3947 /*@ 3948 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 3949 3950 Not Collective 3951 3952 Input Parameters: 3953 + dm - The DMPlex object 3954 - stratumValue - The requested depth 3955 3956 Output Parameters: 3957 + start - The first point at this depth 3958 - end - One beyond the last point at this depth 3959 3960 Notes: 3961 Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 3962 often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 3963 higher dimension, e.g., "edges". 3964 3965 Level: developer 3966 3967 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate() 3968 @*/ 3969 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 3970 { 3971 DMLabel label; 3972 PetscInt pStart, pEnd; 3973 PetscErrorCode ierr; 3974 3975 PetscFunctionBegin; 3976 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3977 if (start) {PetscValidPointer(start, 3); *start = 0;} 3978 if (end) {PetscValidPointer(end, 4); *end = 0;} 3979 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3980 if (pStart == pEnd) PetscFunctionReturn(0); 3981 if (stratumValue < 0) { 3982 if (start) *start = pStart; 3983 if (end) *end = pEnd; 3984 PetscFunctionReturn(0); 3985 } 3986 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3987 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 3988 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 3989 PetscFunctionReturn(0); 3990 } 3991 3992 /*@ 3993 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 3994 3995 Not Collective 3996 3997 Input Parameters: 3998 + dm - The DMPlex object 3999 - stratumValue - The requested height 4000 4001 Output Parameters: 4002 + start - The first point at this height 4003 - end - One beyond the last point at this height 4004 4005 Notes: 4006 Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4007 points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4008 stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4009 4010 Level: developer 4011 4012 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight() 4013 @*/ 4014 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4015 { 4016 DMLabel label; 4017 PetscInt depth, pStart, pEnd; 4018 PetscErrorCode ierr; 4019 4020 PetscFunctionBegin; 4021 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4022 if (start) {PetscValidPointer(start, 3); *start = 0;} 4023 if (end) {PetscValidPointer(end, 4); *end = 0;} 4024 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4025 if (pStart == pEnd) PetscFunctionReturn(0); 4026 if (stratumValue < 0) { 4027 if (start) *start = pStart; 4028 if (end) *end = pEnd; 4029 PetscFunctionReturn(0); 4030 } 4031 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4032 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4033 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 4034 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 4035 PetscFunctionReturn(0); 4036 } 4037 4038 /*@ 4039 DMPlexGetPointDepth - Get the depth of a given point 4040 4041 Not Collective 4042 4043 Input Parameter: 4044 + dm - The DMPlex object 4045 - point - The point 4046 4047 Output Parameter: 4048 . depth - The depth of the point 4049 4050 Level: intermediate 4051 4052 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight() 4053 @*/ 4054 PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4055 { 4056 PetscErrorCode ierr; 4057 4058 PetscFunctionBegin; 4059 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4060 PetscValidIntPointer(depth, 3); 4061 ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr); 4062 PetscFunctionReturn(0); 4063 } 4064 4065 /*@ 4066 DMPlexGetPointHeight - Get the height of a given point 4067 4068 Not Collective 4069 4070 Input Parameter: 4071 + dm - The DMPlex object 4072 - point - The point 4073 4074 Output Parameter: 4075 . height - The height of the point 4076 4077 Level: intermediate 4078 4079 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth() 4080 @*/ 4081 PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 4082 { 4083 PetscInt n, pDepth; 4084 PetscErrorCode ierr; 4085 4086 PetscFunctionBegin; 4087 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4088 PetscValidIntPointer(height, 3); 4089 ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr); 4090 ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr); 4091 *height = n - 1 - pDepth; /* DAG depth is n-1 */ 4092 PetscFunctionReturn(0); 4093 } 4094 4095 /*@ 4096 DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4097 4098 Not Collective 4099 4100 Input Parameter: 4101 . dm - The DMPlex object 4102 4103 Output Parameter: 4104 . celltypeLabel - The DMLabel recording cell polytope type 4105 4106 Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4107 DMCreateLabel(dm, "celltype") beforehand. 4108 4109 Level: developer 4110 4111 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel() 4112 @*/ 4113 PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4114 { 4115 PetscErrorCode ierr; 4116 4117 PetscFunctionBegin; 4118 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4119 PetscValidPointer(celltypeLabel, 2); 4120 if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);} 4121 *celltypeLabel = dm->celltypeLabel; 4122 PetscFunctionReturn(0); 4123 } 4124 4125 /*@ 4126 DMPlexGetCellType - Get the polytope type of a given cell 4127 4128 Not Collective 4129 4130 Input Parameter: 4131 + dm - The DMPlex object 4132 - cell - The cell 4133 4134 Output Parameter: 4135 . celltype - The polytope type of the cell 4136 4137 Level: intermediate 4138 4139 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth() 4140 @*/ 4141 PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4142 { 4143 DMLabel label; 4144 PetscInt ct; 4145 PetscErrorCode ierr; 4146 4147 PetscFunctionBegin; 4148 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4149 PetscValidPointer(celltype, 3); 4150 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4151 ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr); 4152 if (ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell); 4153 *celltype = (DMPolytopeType) ct; 4154 PetscFunctionReturn(0); 4155 } 4156 4157 /*@ 4158 DMPlexSetCellType - Set the polytope type of a given cell 4159 4160 Not Collective 4161 4162 Input Parameters: 4163 + dm - The DMPlex object 4164 . cell - The cell 4165 - celltype - The polytope type of the cell 4166 4167 Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 4168 is executed. This function will override the computed type. However, if automatic classification will not succeed 4169 and a user wants to manually specify all types, the classification must be disabled by calling 4170 DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 4171 4172 Level: advanced 4173 4174 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel() 4175 @*/ 4176 PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 4177 { 4178 DMLabel label; 4179 PetscErrorCode ierr; 4180 4181 PetscFunctionBegin; 4182 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4183 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4184 ierr = DMLabelSetValue(label, cell, celltype);CHKERRQ(ierr); 4185 PetscFunctionReturn(0); 4186 } 4187 4188 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 4189 { 4190 PetscSection section, s; 4191 Mat m; 4192 PetscInt maxHeight; 4193 PetscErrorCode ierr; 4194 4195 PetscFunctionBegin; 4196 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 4197 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 4198 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 4199 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 4200 ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr); 4201 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 4202 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 4203 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 4204 ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr); 4205 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 4206 ierr = MatDestroy(&m);CHKERRQ(ierr); 4207 4208 ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr); 4209 ierr = DMCreateDS(*cdm);CHKERRQ(ierr); 4210 PetscFunctionReturn(0); 4211 } 4212 4213 PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 4214 { 4215 Vec coordsLocal; 4216 DM coordsDM; 4217 PetscErrorCode ierr; 4218 4219 PetscFunctionBegin; 4220 *field = NULL; 4221 ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr); 4222 ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr); 4223 if (coordsLocal && coordsDM) { 4224 ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr); 4225 } 4226 PetscFunctionReturn(0); 4227 } 4228 4229 /*@C 4230 DMPlexGetConeSection - Return a section which describes the layout of cone data 4231 4232 Not Collective 4233 4234 Input Parameters: 4235 . dm - The DMPlex object 4236 4237 Output Parameter: 4238 . section - The PetscSection object 4239 4240 Level: developer 4241 4242 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 4243 @*/ 4244 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 4245 { 4246 DM_Plex *mesh = (DM_Plex*) dm->data; 4247 4248 PetscFunctionBegin; 4249 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4250 if (section) *section = mesh->coneSection; 4251 PetscFunctionReturn(0); 4252 } 4253 4254 /*@C 4255 DMPlexGetSupportSection - Return a section which describes the layout of support data 4256 4257 Not Collective 4258 4259 Input Parameters: 4260 . dm - The DMPlex object 4261 4262 Output Parameter: 4263 . section - The PetscSection object 4264 4265 Level: developer 4266 4267 .seealso: DMPlexGetConeSection() 4268 @*/ 4269 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 4270 { 4271 DM_Plex *mesh = (DM_Plex*) dm->data; 4272 4273 PetscFunctionBegin; 4274 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4275 if (section) *section = mesh->supportSection; 4276 PetscFunctionReturn(0); 4277 } 4278 4279 /*@C 4280 DMPlexGetCones - Return cone data 4281 4282 Not Collective 4283 4284 Input Parameters: 4285 . dm - The DMPlex object 4286 4287 Output Parameter: 4288 . cones - The cone for each point 4289 4290 Level: developer 4291 4292 .seealso: DMPlexGetConeSection() 4293 @*/ 4294 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 4295 { 4296 DM_Plex *mesh = (DM_Plex*) dm->data; 4297 4298 PetscFunctionBegin; 4299 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4300 if (cones) *cones = mesh->cones; 4301 PetscFunctionReturn(0); 4302 } 4303 4304 /*@C 4305 DMPlexGetConeOrientations - Return cone orientation data 4306 4307 Not Collective 4308 4309 Input Parameters: 4310 . dm - The DMPlex object 4311 4312 Output Parameter: 4313 . coneOrientations - The cone orientation for each point 4314 4315 Level: developer 4316 4317 .seealso: DMPlexGetConeSection() 4318 @*/ 4319 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 4320 { 4321 DM_Plex *mesh = (DM_Plex*) dm->data; 4322 4323 PetscFunctionBegin; 4324 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4325 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 4326 PetscFunctionReturn(0); 4327 } 4328 4329 /******************************** FEM Support **********************************/ 4330 4331 /* 4332 Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 4333 representing a line in the section. 4334 */ 4335 static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 4336 { 4337 PetscErrorCode ierr; 4338 4339 PetscFunctionBeginHot; 4340 ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr); 4341 if (line < 0) { 4342 *k = 0; 4343 *Nc = 0; 4344 } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 4345 *k = 1; 4346 } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 4347 /* An order k SEM disc has k-1 dofs on an edge */ 4348 ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr); 4349 *k = *k / *Nc + 1; 4350 } 4351 PetscFunctionReturn(0); 4352 } 4353 4354 /*@ 4355 4356 DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 4357 lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 4358 section provided (or the section of the DM). 4359 4360 Input Parameters: 4361 + dm - The DM 4362 . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 4363 - section - The PetscSection to reorder, or NULL for the default section 4364 4365 Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 4366 degree of the basis. 4367 4368 Example: 4369 A typical interpolated single-quad mesh might order points as 4370 .vb 4371 [c0, v1, v2, v3, v4, e5, e6, e7, e8] 4372 4373 v4 -- e6 -- v3 4374 | | 4375 e7 c0 e8 4376 | | 4377 v1 -- e5 -- v2 4378 .ve 4379 4380 (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 4381 dofs in the order of points, e.g., 4382 .vb 4383 c0 -> [0,1,2,3] 4384 v1 -> [4] 4385 ... 4386 e5 -> [8, 9] 4387 .ve 4388 4389 which corresponds to the dofs 4390 .vb 4391 6 10 11 7 4392 13 2 3 15 4393 12 0 1 14 4394 4 8 9 5 4395 .ve 4396 4397 The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 4398 .vb 4399 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 4400 .ve 4401 4402 After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 4403 .vb 4404 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 4405 .ve 4406 4407 Level: developer 4408 4409 .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection() 4410 @*/ 4411 PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 4412 { 4413 DMLabel label; 4414 PetscInt dim, depth = -1, eStart = -1, Nf; 4415 PetscBool vertexchart; 4416 PetscErrorCode ierr; 4417 4418 PetscFunctionBegin; 4419 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4420 if (dim < 1) PetscFunctionReturn(0); 4421 if (point < 0) { 4422 PetscInt sStart,sEnd; 4423 4424 ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr); 4425 point = sEnd-sStart ? sStart : point; 4426 } 4427 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4428 if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); } 4429 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 4430 if (depth == 1) {eStart = point;} 4431 else if (depth == dim) { 4432 const PetscInt *cone; 4433 4434 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4435 if (dim == 2) eStart = cone[0]; 4436 else if (dim == 3) { 4437 const PetscInt *cone2; 4438 ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 4439 eStart = cone2[0]; 4440 } 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); 4441 } 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); 4442 { /* Determine whether the chart covers all points or just vertices. */ 4443 PetscInt pStart,pEnd,cStart,cEnd; 4444 ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr); 4445 ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr); 4446 if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Just vertices */ 4447 else vertexchart = PETSC_FALSE; /* Assume all interpolated points are in chart */ 4448 } 4449 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 4450 for (PetscInt d=1; d<=dim; d++) { 4451 PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 4452 PetscInt *perm; 4453 4454 for (f = 0; f < Nf; ++f) { 4455 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 4456 size += PetscPowInt(k+1, d)*Nc; 4457 } 4458 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 4459 for (f = 0; f < Nf; ++f) { 4460 switch (d) { 4461 case 1: 4462 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 4463 /* 4464 Original ordering is [ edge of length k-1; vtx0; vtx1 ] 4465 We want [ vtx0; edge of length k-1; vtx1 ] 4466 */ 4467 for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 4468 for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 4469 for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 4470 foffset = offset; 4471 break; 4472 case 2: 4473 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 4474 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 4475 /* The SEM order is 4476 4477 v_lb, {e_b}, v_rb, 4478 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 4479 v_lt, reverse {e_t}, v_rt 4480 */ 4481 { 4482 const PetscInt of = 0; 4483 const PetscInt oeb = of + PetscSqr(k-1); 4484 const PetscInt oer = oeb + (k-1); 4485 const PetscInt oet = oer + (k-1); 4486 const PetscInt oel = oet + (k-1); 4487 const PetscInt ovlb = oel + (k-1); 4488 const PetscInt ovrb = ovlb + 1; 4489 const PetscInt ovrt = ovrb + 1; 4490 const PetscInt ovlt = ovrt + 1; 4491 PetscInt o; 4492 4493 /* bottom */ 4494 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 4495 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4496 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 4497 /* middle */ 4498 for (i = 0; i < k-1; ++i) { 4499 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 4500 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; 4501 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 4502 } 4503 /* top */ 4504 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 4505 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4506 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 4507 foffset = offset; 4508 } 4509 break; 4510 case 3: 4511 /* The original hex closure is 4512 4513 {c, 4514 f_b, f_t, f_f, f_b, f_r, f_l, 4515 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 4516 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 4517 */ 4518 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 4519 /* The SEM order is 4520 Bottom Slice 4521 v_blf, {e^{(k-1)-n}_bf}, v_brf, 4522 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 4523 v_blb, {e_bb}, v_brb, 4524 4525 Middle Slice (j) 4526 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 4527 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 4528 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 4529 4530 Top Slice 4531 v_tlf, {e_tf}, v_trf, 4532 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 4533 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 4534 */ 4535 { 4536 const PetscInt oc = 0; 4537 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 4538 const PetscInt oft = ofb + PetscSqr(k-1); 4539 const PetscInt off = oft + PetscSqr(k-1); 4540 const PetscInt ofk = off + PetscSqr(k-1); 4541 const PetscInt ofr = ofk + PetscSqr(k-1); 4542 const PetscInt ofl = ofr + PetscSqr(k-1); 4543 const PetscInt oebl = ofl + PetscSqr(k-1); 4544 const PetscInt oebb = oebl + (k-1); 4545 const PetscInt oebr = oebb + (k-1); 4546 const PetscInt oebf = oebr + (k-1); 4547 const PetscInt oetf = oebf + (k-1); 4548 const PetscInt oetr = oetf + (k-1); 4549 const PetscInt oetb = oetr + (k-1); 4550 const PetscInt oetl = oetb + (k-1); 4551 const PetscInt oerf = oetl + (k-1); 4552 const PetscInt oelf = oerf + (k-1); 4553 const PetscInt oelb = oelf + (k-1); 4554 const PetscInt oerb = oelb + (k-1); 4555 const PetscInt ovblf = oerb + (k-1); 4556 const PetscInt ovblb = ovblf + 1; 4557 const PetscInt ovbrb = ovblb + 1; 4558 const PetscInt ovbrf = ovbrb + 1; 4559 const PetscInt ovtlf = ovbrf + 1; 4560 const PetscInt ovtrf = ovtlf + 1; 4561 const PetscInt ovtrb = ovtrf + 1; 4562 const PetscInt ovtlb = ovtrb + 1; 4563 PetscInt o, n; 4564 4565 /* Bottom Slice */ 4566 /* bottom */ 4567 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 4568 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4569 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 4570 /* middle */ 4571 for (i = 0; i < k-1; ++i) { 4572 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 4573 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;} 4574 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 4575 } 4576 /* top */ 4577 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 4578 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4579 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 4580 4581 /* Middle Slice */ 4582 for (j = 0; j < k-1; ++j) { 4583 /* bottom */ 4584 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 4585 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; 4586 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 4587 /* middle */ 4588 for (i = 0; i < k-1; ++i) { 4589 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 4590 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; 4591 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 4592 } 4593 /* top */ 4594 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 4595 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; 4596 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 4597 } 4598 4599 /* Top Slice */ 4600 /* bottom */ 4601 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 4602 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4603 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 4604 /* middle */ 4605 for (i = 0; i < k-1; ++i) { 4606 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 4607 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 4608 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 4609 } 4610 /* top */ 4611 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 4612 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4613 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 4614 4615 foffset = offset; 4616 } 4617 break; 4618 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d); 4619 } 4620 } 4621 if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 4622 /* Check permutation */ 4623 { 4624 PetscInt *check; 4625 4626 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 4627 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]);} 4628 for (i = 0; i < size; ++i) check[perm[i]] = i; 4629 for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 4630 ierr = PetscFree(check);CHKERRQ(ierr); 4631 } 4632 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 4633 } 4634 PetscFunctionReturn(0); 4635 } 4636 4637 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 4638 { 4639 PetscDS prob; 4640 PetscInt depth, Nf, h; 4641 DMLabel label; 4642 PetscErrorCode ierr; 4643 4644 PetscFunctionBeginHot; 4645 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 4646 Nf = prob->Nf; 4647 label = dm->depthLabel; 4648 *dspace = NULL; 4649 if (field < Nf) { 4650 PetscObject disc = prob->disc[field]; 4651 4652 if (disc->classid == PETSCFE_CLASSID) { 4653 PetscDualSpace dsp; 4654 4655 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 4656 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 4657 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 4658 h = depth - 1 - h; 4659 if (h) { 4660 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 4661 } else { 4662 *dspace = dsp; 4663 } 4664 } 4665 } 4666 PetscFunctionReturn(0); 4667 } 4668 4669 4670 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4671 { 4672 PetscScalar *array, *vArray; 4673 const PetscInt *cone, *coneO; 4674 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 4675 PetscErrorCode ierr; 4676 4677 PetscFunctionBeginHot; 4678 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4679 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 4680 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4681 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 4682 if (!values || !*values) { 4683 if ((point >= pStart) && (point < pEnd)) { 4684 PetscInt dof; 4685 4686 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4687 size += dof; 4688 } 4689 for (p = 0; p < numPoints; ++p) { 4690 const PetscInt cp = cone[p]; 4691 PetscInt dof; 4692 4693 if ((cp < pStart) || (cp >= pEnd)) continue; 4694 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4695 size += dof; 4696 } 4697 if (!values) { 4698 if (csize) *csize = size; 4699 PetscFunctionReturn(0); 4700 } 4701 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 4702 } else { 4703 array = *values; 4704 } 4705 size = 0; 4706 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 4707 if ((point >= pStart) && (point < pEnd)) { 4708 PetscInt dof, off, d; 4709 PetscScalar *varr; 4710 4711 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4712 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4713 varr = &vArray[off]; 4714 for (d = 0; d < dof; ++d, ++offset) { 4715 array[offset] = varr[d]; 4716 } 4717 size += dof; 4718 } 4719 for (p = 0; p < numPoints; ++p) { 4720 const PetscInt cp = cone[p]; 4721 PetscInt o = coneO[p]; 4722 PetscInt dof, off, d; 4723 PetscScalar *varr; 4724 4725 if ((cp < pStart) || (cp >= pEnd)) continue; 4726 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4727 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 4728 varr = &vArray[off]; 4729 if (o >= 0) { 4730 for (d = 0; d < dof; ++d, ++offset) { 4731 array[offset] = varr[d]; 4732 } 4733 } else { 4734 for (d = dof-1; d >= 0; --d, ++offset) { 4735 array[offset] = varr[d]; 4736 } 4737 } 4738 size += dof; 4739 } 4740 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 4741 if (!*values) { 4742 if (csize) *csize = size; 4743 *values = array; 4744 } else { 4745 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 4746 *csize = size; 4747 } 4748 PetscFunctionReturn(0); 4749 } 4750 4751 /* Compress out points not in the section */ 4752 PETSC_STATIC_INLINE PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 4753 { 4754 const PetscInt np = *numPoints; 4755 PetscInt pStart, pEnd, p, q; 4756 PetscErrorCode ierr; 4757 4758 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4759 for (p = 0, q = 0; p < np; ++p) { 4760 const PetscInt r = points[p*2]; 4761 if ((r >= pStart) && (r < pEnd)) { 4762 points[q*2] = r; 4763 points[q*2+1] = points[p*2+1]; 4764 ++q; 4765 } 4766 } 4767 *numPoints = q; 4768 return 0; 4769 } 4770 4771 static PetscErrorCode DMPlexTransitiveClosure_Hybrid_Internal(DM dm, PetscInt point, PetscInt np, PetscInt *numPoints, PetscInt **points) 4772 { 4773 const PetscInt *cone, *ornt; 4774 PetscInt *pts, *closure = NULL; 4775 PetscInt dim, coneSize, c, d, clSize, cl; 4776 PetscErrorCode ierr; 4777 4778 PetscFunctionBeginHot; 4779 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4780 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4781 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4782 ierr = DMPlexGetConeOrientation(dm, point, &ornt);CHKERRQ(ierr); 4783 ierr = DMPlexGetTransitiveClosure(dm, cone[0], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 4784 ierr = DMGetWorkArray(dm, np*2, MPIU_INT, &pts);CHKERRQ(ierr); 4785 c = 0; 4786 pts[c*2+0] = point; 4787 pts[c*2+1] = 0; 4788 ++c; 4789 for (cl = 0; cl < clSize*2; cl += 2, ++c) {pts[c*2+0] = closure[cl]; pts[c*2+1] = closure[cl+1];} 4790 ierr = DMPlexGetTransitiveClosure(dm, cone[1], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 4791 for (cl = 0; cl < clSize*2; cl += 2, ++c) {pts[c*2+0] = closure[cl]; pts[c*2+1] = closure[cl+1];} 4792 ierr = DMPlexRestoreTransitiveClosure(dm, cone[0], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 4793 if (dim >= 2) { 4794 for (d = 2; d < coneSize; ++d, ++c) {pts[c*2+0] = cone[d]; pts[c*2+1] = ornt[d];} 4795 } 4796 if (dim >= 3) { 4797 for (d = 2; d < coneSize; ++d) { 4798 const PetscInt fpoint = cone[d]; 4799 const PetscInt *fcone; 4800 PetscInt fconeSize, fc, i; 4801 4802 ierr = DMPlexGetConeSize(dm, fpoint, &fconeSize);CHKERRQ(ierr); 4803 ierr = DMPlexGetCone(dm, fpoint, &fcone);CHKERRQ(ierr); 4804 for (fc = 0; fc < fconeSize; ++fc) { 4805 for (i = 0; i < c; ++i) if (pts[i*2] == fcone[fc]) break; 4806 if (i == c) {pts[c*2+0] = fcone[fc]; pts[c*2+1] = 0; ++c;} 4807 } 4808 } 4809 } 4810 if (c != np) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid closure for hybrid point %D, size %D != %D", point, c, np); 4811 *numPoints = np; 4812 *points = pts; 4813 PetscFunctionReturn(0); 4814 } 4815 4816 /* Compressed closure does not apply closure permutation */ 4817 PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 4818 { 4819 const PetscInt *cla = NULL; 4820 PetscInt np, *pts = NULL; 4821 PetscErrorCode ierr; 4822 4823 PetscFunctionBeginHot; 4824 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 4825 if (*clPoints) { 4826 PetscInt dof, off; 4827 4828 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 4829 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 4830 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 4831 np = dof/2; 4832 pts = (PetscInt *) &cla[off]; 4833 } else { 4834 DMPolytopeType ct; 4835 4836 /* Do not make the label if it does not exist */ 4837 if (!dm->celltypeLabel) {ct = DM_POLYTOPE_POINT;} 4838 else {ierr = DMPlexGetCellType(dm, point, &ct);CHKERRQ(ierr);} 4839 switch (ct) { 4840 case DM_POLYTOPE_SEG_PRISM_TENSOR: 4841 ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 9, &np, &pts);CHKERRQ(ierr); 4842 break; 4843 case DM_POLYTOPE_TRI_PRISM_TENSOR: 4844 ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 21, &np, &pts);CHKERRQ(ierr); 4845 break; 4846 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 4847 ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 27, &np, &pts);CHKERRQ(ierr); 4848 break; 4849 default: 4850 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 4851 } 4852 ierr = CompressPoints_Private(section, &np, pts);CHKERRQ(ierr); 4853 } 4854 *numPoints = np; 4855 *points = pts; 4856 *clp = cla; 4857 PetscFunctionReturn(0); 4858 } 4859 4860 PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 4861 { 4862 PetscErrorCode ierr; 4863 4864 PetscFunctionBeginHot; 4865 if (!*clPoints) { 4866 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 4867 } else { 4868 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 4869 } 4870 *numPoints = 0; 4871 *points = NULL; 4872 *clSec = NULL; 4873 *clPoints = NULL; 4874 *clp = NULL; 4875 PetscFunctionReturn(0); 4876 } 4877 4878 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[]) 4879 { 4880 PetscInt offset = 0, p; 4881 const PetscInt **perms = NULL; 4882 const PetscScalar **flips = NULL; 4883 PetscErrorCode ierr; 4884 4885 PetscFunctionBeginHot; 4886 *size = 0; 4887 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4888 for (p = 0; p < numPoints; p++) { 4889 const PetscInt point = points[2*p]; 4890 const PetscInt *perm = perms ? perms[p] : NULL; 4891 const PetscScalar *flip = flips ? flips[p] : NULL; 4892 PetscInt dof, off, d; 4893 const PetscScalar *varr; 4894 4895 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4896 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4897 varr = &vArray[off]; 4898 if (clperm) { 4899 if (perm) { 4900 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 4901 } else { 4902 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 4903 } 4904 if (flip) { 4905 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 4906 } 4907 } else { 4908 if (perm) { 4909 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 4910 } else { 4911 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 4912 } 4913 if (flip) { 4914 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 4915 } 4916 } 4917 offset += dof; 4918 } 4919 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4920 *size = offset; 4921 PetscFunctionReturn(0); 4922 } 4923 4924 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[]) 4925 { 4926 PetscInt offset = 0, f; 4927 PetscErrorCode ierr; 4928 4929 PetscFunctionBeginHot; 4930 *size = 0; 4931 for (f = 0; f < numFields; ++f) { 4932 PetscInt p; 4933 const PetscInt **perms = NULL; 4934 const PetscScalar **flips = NULL; 4935 4936 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4937 for (p = 0; p < numPoints; p++) { 4938 const PetscInt point = points[2*p]; 4939 PetscInt fdof, foff, b; 4940 const PetscScalar *varr; 4941 const PetscInt *perm = perms ? perms[p] : NULL; 4942 const PetscScalar *flip = flips ? flips[p] : NULL; 4943 4944 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4945 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4946 varr = &vArray[foff]; 4947 if (clperm) { 4948 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 4949 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 4950 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 4951 } else { 4952 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 4953 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 4954 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 4955 } 4956 offset += fdof; 4957 } 4958 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4959 } 4960 *size = offset; 4961 PetscFunctionReturn(0); 4962 } 4963 4964 /*@C 4965 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 4966 4967 Not collective 4968 4969 Input Parameters: 4970 + dm - The DM 4971 . section - The section describing the layout in v, or NULL to use the default section 4972 . v - The local vector 4973 . point - The point in the DM 4974 . csize - The size of the input values array, or NULL 4975 - values - An array to use for the values, or NULL to have it allocated automatically 4976 4977 Output Parameters: 4978 + csize - The number of values in the closure 4979 - values - The array of values. If the user provided NULL, it is a borrowed array and should not be freed 4980 4981 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 4982 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 4983 $ assembly function, and a user may already have allocated storage for this operation. 4984 $ 4985 $ A typical use could be 4986 $ 4987 $ values = NULL; 4988 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4989 $ for (cl = 0; cl < clSize; ++cl) { 4990 $ <Compute on closure> 4991 $ } 4992 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4993 $ 4994 $ or 4995 $ 4996 $ PetscMalloc1(clMaxSize, &values); 4997 $ for (p = pStart; p < pEnd; ++p) { 4998 $ clSize = clMaxSize; 4999 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5000 $ for (cl = 0; cl < clSize; ++cl) { 5001 $ <Compute on closure> 5002 $ } 5003 $ } 5004 $ PetscFree(values); 5005 5006 Fortran Notes: 5007 Since it returns an array, this routine is only available in Fortran 90, and you must 5008 include petsc.h90 in your code. 5009 5010 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5011 5012 Level: intermediate 5013 5014 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5015 @*/ 5016 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5017 { 5018 PetscSection clSection; 5019 IS clPoints; 5020 PetscInt *points = NULL; 5021 const PetscInt *clp, *perm; 5022 PetscInt depth, numFields, numPoints, asize; 5023 PetscErrorCode ierr; 5024 5025 PetscFunctionBeginHot; 5026 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5027 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5028 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5029 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5030 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5031 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5032 if (depth == 1 && numFields < 2) { 5033 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5034 PetscFunctionReturn(0); 5035 } 5036 /* Get points */ 5037 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5038 /* Get sizes */ 5039 asize = 0; 5040 for (PetscInt p = 0; p < numPoints*2; p += 2) { 5041 PetscInt dof; 5042 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5043 asize += dof; 5044 } 5045 if (values) { 5046 const PetscScalar *vArray; 5047 PetscInt size; 5048 5049 if (*values) { 5050 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); 5051 } else {ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, values);CHKERRQ(ierr);} 5052 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm);CHKERRQ(ierr); 5053 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5054 /* Get values */ 5055 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values);CHKERRQ(ierr);} 5056 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values);CHKERRQ(ierr);} 5057 if (PetscUnlikely(asize != size)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size); 5058 /* Cleanup array */ 5059 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5060 } 5061 if (csize) *csize = asize; 5062 /* Cleanup points */ 5063 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5064 PetscFunctionReturn(0); 5065 } 5066 5067 PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5068 { 5069 DMLabel depthLabel; 5070 PetscSection clSection; 5071 IS clPoints; 5072 PetscScalar *array; 5073 const PetscScalar *vArray; 5074 PetscInt *points = NULL; 5075 const PetscInt *clp, *perm = NULL; 5076 PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5077 PetscErrorCode ierr; 5078 5079 PetscFunctionBeginHot; 5080 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5081 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5082 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5083 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5084 ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr); 5085 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 5086 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5087 if (mdepth == 1 && numFields < 2) { 5088 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5089 PetscFunctionReturn(0); 5090 } 5091 /* Get points */ 5092 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5093 for (clsize=0,p=0; p<Np; p++) { 5094 PetscInt dof; 5095 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 5096 clsize += dof; 5097 } 5098 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm);CHKERRQ(ierr); 5099 /* Filter points */ 5100 for (p = 0; p < numPoints*2; p += 2) { 5101 PetscInt dep; 5102 5103 ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr); 5104 if (dep != depth) continue; 5105 points[Np*2+0] = points[p]; 5106 points[Np*2+1] = points[p+1]; 5107 ++Np; 5108 } 5109 /* Get array */ 5110 if (!values || !*values) { 5111 PetscInt asize = 0, dof; 5112 5113 for (p = 0; p < Np*2; p += 2) { 5114 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5115 asize += dof; 5116 } 5117 if (!values) { 5118 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5119 if (csize) *csize = asize; 5120 PetscFunctionReturn(0); 5121 } 5122 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 5123 } else { 5124 array = *values; 5125 } 5126 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5127 /* Get values */ 5128 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 5129 else {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);} 5130 /* Cleanup points */ 5131 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5132 /* Cleanup array */ 5133 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5134 if (!*values) { 5135 if (csize) *csize = size; 5136 *values = array; 5137 } else { 5138 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5139 *csize = size; 5140 } 5141 PetscFunctionReturn(0); 5142 } 5143 5144 /*@C 5145 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5146 5147 Not collective 5148 5149 Input Parameters: 5150 + dm - The DM 5151 . section - The section describing the layout in v, or NULL to use the default section 5152 . v - The local vector 5153 . point - The point in the DM 5154 . csize - The number of values in the closure, or NULL 5155 - values - The array of values, which is a borrowed array and should not be freed 5156 5157 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 5158 5159 Fortran Notes: 5160 Since it returns an array, this routine is only available in Fortran 90, and you must 5161 include petsc.h90 in your code. 5162 5163 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5164 5165 Level: intermediate 5166 5167 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5168 @*/ 5169 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5170 { 5171 PetscInt size = 0; 5172 PetscErrorCode ierr; 5173 5174 PetscFunctionBegin; 5175 /* Should work without recalculating size */ 5176 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 5177 *values = NULL; 5178 PetscFunctionReturn(0); 5179 } 5180 5181 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 5182 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5183 5184 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[]) 5185 { 5186 PetscInt cdof; /* The number of constraints on this point */ 5187 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5188 PetscScalar *a; 5189 PetscInt off, cind = 0, k; 5190 PetscErrorCode ierr; 5191 5192 PetscFunctionBegin; 5193 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5194 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5195 a = &array[off]; 5196 if (!cdof || setBC) { 5197 if (clperm) { 5198 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 5199 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5200 } else { 5201 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 5202 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5203 } 5204 } else { 5205 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5206 if (clperm) { 5207 if (perm) {for (k = 0; k < dof; ++k) { 5208 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5209 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5210 } 5211 } else { 5212 for (k = 0; k < dof; ++k) { 5213 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5214 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5215 } 5216 } 5217 } else { 5218 if (perm) { 5219 for (k = 0; k < dof; ++k) { 5220 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5221 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5222 } 5223 } else { 5224 for (k = 0; k < dof; ++k) { 5225 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5226 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5227 } 5228 } 5229 } 5230 } 5231 PetscFunctionReturn(0); 5232 } 5233 5234 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[]) 5235 { 5236 PetscInt cdof; /* The number of constraints on this point */ 5237 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5238 PetscScalar *a; 5239 PetscInt off, cind = 0, k; 5240 PetscErrorCode ierr; 5241 5242 PetscFunctionBegin; 5243 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5244 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5245 a = &array[off]; 5246 if (cdof) { 5247 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5248 if (clperm) { 5249 if (perm) { 5250 for (k = 0; k < dof; ++k) { 5251 if ((cind < cdof) && (k == cdofs[cind])) { 5252 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5253 cind++; 5254 } 5255 } 5256 } else { 5257 for (k = 0; k < dof; ++k) { 5258 if ((cind < cdof) && (k == cdofs[cind])) { 5259 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5260 cind++; 5261 } 5262 } 5263 } 5264 } else { 5265 if (perm) { 5266 for (k = 0; k < dof; ++k) { 5267 if ((cind < cdof) && (k == cdofs[cind])) { 5268 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5269 cind++; 5270 } 5271 } 5272 } else { 5273 for (k = 0; k < dof; ++k) { 5274 if ((cind < cdof) && (k == cdofs[cind])) { 5275 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5276 cind++; 5277 } 5278 } 5279 } 5280 } 5281 } 5282 PetscFunctionReturn(0); 5283 } 5284 5285 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[]) 5286 { 5287 PetscScalar *a; 5288 PetscInt fdof, foff, fcdof, foffset = *offset; 5289 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5290 PetscInt cind = 0, b; 5291 PetscErrorCode ierr; 5292 5293 PetscFunctionBegin; 5294 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5295 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 5296 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5297 a = &array[foff]; 5298 if (!fcdof || setBC) { 5299 if (clperm) { 5300 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 5301 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 5302 } else { 5303 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 5304 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 5305 } 5306 } else { 5307 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5308 if (clperm) { 5309 if (perm) { 5310 for (b = 0; b < fdof; b++) { 5311 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5312 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 5313 } 5314 } else { 5315 for (b = 0; b < fdof; b++) { 5316 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5317 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 5318 } 5319 } 5320 } else { 5321 if (perm) { 5322 for (b = 0; b < fdof; b++) { 5323 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5324 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 5325 } 5326 } else { 5327 for (b = 0; b < fdof; b++) { 5328 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5329 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 5330 } 5331 } 5332 } 5333 } 5334 *offset += fdof; 5335 PetscFunctionReturn(0); 5336 } 5337 5338 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[]) 5339 { 5340 PetscScalar *a; 5341 PetscInt fdof, foff, fcdof, foffset = *offset; 5342 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5343 PetscInt Nc, cind = 0, ncind = 0, b; 5344 PetscBool ncSet, fcSet; 5345 PetscErrorCode ierr; 5346 5347 PetscFunctionBegin; 5348 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 5349 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5350 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 5351 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5352 a = &array[foff]; 5353 if (fcdof) { 5354 /* We just override fcdof and fcdofs with Ncc and comps */ 5355 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5356 if (clperm) { 5357 if (perm) { 5358 if (comps) { 5359 for (b = 0; b < fdof; b++) { 5360 ncSet = fcSet = PETSC_FALSE; 5361 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5362 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5363 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 5364 } 5365 } else { 5366 for (b = 0; b < fdof; b++) { 5367 if ((cind < fcdof) && (b == fcdofs[cind])) { 5368 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 5369 ++cind; 5370 } 5371 } 5372 } 5373 } else { 5374 if (comps) { 5375 for (b = 0; b < fdof; b++) { 5376 ncSet = fcSet = PETSC_FALSE; 5377 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5378 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5379 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 5380 } 5381 } else { 5382 for (b = 0; b < fdof; b++) { 5383 if ((cind < fcdof) && (b == fcdofs[cind])) { 5384 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 5385 ++cind; 5386 } 5387 } 5388 } 5389 } 5390 } else { 5391 if (perm) { 5392 if (comps) { 5393 for (b = 0; b < fdof; b++) { 5394 ncSet = fcSet = PETSC_FALSE; 5395 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5396 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5397 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 5398 } 5399 } else { 5400 for (b = 0; b < fdof; b++) { 5401 if ((cind < fcdof) && (b == fcdofs[cind])) { 5402 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 5403 ++cind; 5404 } 5405 } 5406 } 5407 } else { 5408 if (comps) { 5409 for (b = 0; b < fdof; b++) { 5410 ncSet = fcSet = PETSC_FALSE; 5411 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5412 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5413 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 5414 } 5415 } else { 5416 for (b = 0; b < fdof; b++) { 5417 if ((cind < fcdof) && (b == fcdofs[cind])) { 5418 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 5419 ++cind; 5420 } 5421 } 5422 } 5423 } 5424 } 5425 } 5426 *offset += fdof; 5427 PetscFunctionReturn(0); 5428 } 5429 5430 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 5431 { 5432 PetscScalar *array; 5433 const PetscInt *cone, *coneO; 5434 PetscInt pStart, pEnd, p, numPoints, off, dof; 5435 PetscErrorCode ierr; 5436 5437 PetscFunctionBeginHot; 5438 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5439 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5440 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5441 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5442 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 5443 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 5444 const PetscInt cp = !p ? point : cone[p-1]; 5445 const PetscInt o = !p ? 0 : coneO[p-1]; 5446 5447 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 5448 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5449 /* ADD_VALUES */ 5450 { 5451 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5452 PetscScalar *a; 5453 PetscInt cdof, coff, cind = 0, k; 5454 5455 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 5456 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 5457 a = &array[coff]; 5458 if (!cdof) { 5459 if (o >= 0) { 5460 for (k = 0; k < dof; ++k) { 5461 a[k] += values[off+k]; 5462 } 5463 } else { 5464 for (k = 0; k < dof; ++k) { 5465 a[k] += values[off+dof-k-1]; 5466 } 5467 } 5468 } else { 5469 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 5470 if (o >= 0) { 5471 for (k = 0; k < dof; ++k) { 5472 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5473 a[k] += values[off+k]; 5474 } 5475 } else { 5476 for (k = 0; k < dof; ++k) { 5477 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5478 a[k] += values[off+dof-k-1]; 5479 } 5480 } 5481 } 5482 } 5483 } 5484 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 5485 PetscFunctionReturn(0); 5486 } 5487 5488 /*@C 5489 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 5490 5491 Not collective 5492 5493 Input Parameters: 5494 + dm - The DM 5495 . section - The section describing the layout in v, or NULL to use the default section 5496 . v - The local vector 5497 . point - The point in the DM 5498 . values - The array of values 5499 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 5500 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 5501 5502 Fortran Notes: 5503 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 5504 5505 Level: intermediate 5506 5507 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 5508 @*/ 5509 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 5510 { 5511 PetscSection clSection; 5512 IS clPoints; 5513 PetscScalar *array; 5514 PetscInt *points = NULL; 5515 const PetscInt *clp, *clperm = NULL; 5516 PetscInt depth, numFields, numPoints, p, clsize; 5517 PetscErrorCode ierr; 5518 5519 PetscFunctionBeginHot; 5520 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5521 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5522 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5523 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5524 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5525 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5526 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 5527 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 5528 PetscFunctionReturn(0); 5529 } 5530 /* Get points */ 5531 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5532 for (clsize=0,p=0; p<numPoints; p++) { 5533 PetscInt dof; 5534 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 5535 clsize += dof; 5536 } 5537 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 5538 /* Get array */ 5539 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 5540 /* Get values */ 5541 if (numFields > 0) { 5542 PetscInt offset = 0, f; 5543 for (f = 0; f < numFields; ++f) { 5544 const PetscInt **perms = NULL; 5545 const PetscScalar **flips = NULL; 5546 5547 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5548 switch (mode) { 5549 case INSERT_VALUES: 5550 for (p = 0; p < numPoints; p++) { 5551 const PetscInt point = points[2*p]; 5552 const PetscInt *perm = perms ? perms[p] : NULL; 5553 const PetscScalar *flip = flips ? flips[p] : NULL; 5554 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 5555 } break; 5556 case INSERT_ALL_VALUES: 5557 for (p = 0; p < numPoints; p++) { 5558 const PetscInt point = points[2*p]; 5559 const PetscInt *perm = perms ? perms[p] : NULL; 5560 const PetscScalar *flip = flips ? flips[p] : NULL; 5561 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 5562 } break; 5563 case INSERT_BC_VALUES: 5564 for (p = 0; p < numPoints; p++) { 5565 const PetscInt point = points[2*p]; 5566 const PetscInt *perm = perms ? perms[p] : NULL; 5567 const PetscScalar *flip = flips ? flips[p] : NULL; 5568 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 5569 } break; 5570 case ADD_VALUES: 5571 for (p = 0; p < numPoints; p++) { 5572 const PetscInt point = points[2*p]; 5573 const PetscInt *perm = perms ? perms[p] : NULL; 5574 const PetscScalar *flip = flips ? flips[p] : NULL; 5575 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 5576 } break; 5577 case ADD_ALL_VALUES: 5578 for (p = 0; p < numPoints; p++) { 5579 const PetscInt point = points[2*p]; 5580 const PetscInt *perm = perms ? perms[p] : NULL; 5581 const PetscScalar *flip = flips ? flips[p] : NULL; 5582 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 5583 } break; 5584 case ADD_BC_VALUES: 5585 for (p = 0; p < numPoints; p++) { 5586 const PetscInt point = points[2*p]; 5587 const PetscInt *perm = perms ? perms[p] : NULL; 5588 const PetscScalar *flip = flips ? flips[p] : NULL; 5589 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 5590 } break; 5591 default: 5592 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 5593 } 5594 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5595 } 5596 } else { 5597 PetscInt dof, off; 5598 const PetscInt **perms = NULL; 5599 const PetscScalar **flips = NULL; 5600 5601 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5602 switch (mode) { 5603 case INSERT_VALUES: 5604 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 5605 const PetscInt point = points[2*p]; 5606 const PetscInt *perm = perms ? perms[p] : NULL; 5607 const PetscScalar *flip = flips ? flips[p] : NULL; 5608 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5609 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 5610 } break; 5611 case INSERT_ALL_VALUES: 5612 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 5613 const PetscInt point = points[2*p]; 5614 const PetscInt *perm = perms ? perms[p] : NULL; 5615 const PetscScalar *flip = flips ? flips[p] : NULL; 5616 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5617 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 5618 } break; 5619 case INSERT_BC_VALUES: 5620 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 5621 const PetscInt point = points[2*p]; 5622 const PetscInt *perm = perms ? perms[p] : NULL; 5623 const PetscScalar *flip = flips ? flips[p] : NULL; 5624 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5625 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 5626 } break; 5627 case ADD_VALUES: 5628 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 5629 const PetscInt point = points[2*p]; 5630 const PetscInt *perm = perms ? perms[p] : NULL; 5631 const PetscScalar *flip = flips ? flips[p] : NULL; 5632 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5633 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 5634 } break; 5635 case ADD_ALL_VALUES: 5636 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 5637 const PetscInt point = points[2*p]; 5638 const PetscInt *perm = perms ? perms[p] : NULL; 5639 const PetscScalar *flip = flips ? flips[p] : NULL; 5640 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5641 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 5642 } break; 5643 case ADD_BC_VALUES: 5644 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 5645 const PetscInt point = points[2*p]; 5646 const PetscInt *perm = perms ? perms[p] : NULL; 5647 const PetscScalar *flip = flips ? flips[p] : NULL; 5648 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5649 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 5650 } break; 5651 default: 5652 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 5653 } 5654 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5655 } 5656 /* Cleanup points */ 5657 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5658 /* Cleanup array */ 5659 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 5660 PetscFunctionReturn(0); 5661 } 5662 5663 /* Check whether the given point is in the label. If not, update the offset to skip this point */ 5664 PETSC_STATIC_INLINE PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 5665 { 5666 PetscFunctionBegin; 5667 if (label) { 5668 PetscInt val, fdof; 5669 PetscErrorCode ierr; 5670 5671 /* There is a problem with this: 5672 Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that 5673 touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell. 5674 Thus I am only going to check val != -1, not val != labelId 5675 */ 5676 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 5677 if (val < 0) { 5678 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5679 *offset += fdof; 5680 PetscFunctionReturn(1); 5681 } 5682 } 5683 PetscFunctionReturn(0); 5684 } 5685 5686 /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 5687 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) 5688 { 5689 PetscSection clSection; 5690 IS clPoints; 5691 PetscScalar *array; 5692 PetscInt *points = NULL; 5693 const PetscInt *clp; 5694 PetscInt numFields, numPoints, p; 5695 PetscInt offset = 0, f; 5696 PetscErrorCode ierr; 5697 5698 PetscFunctionBeginHot; 5699 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5700 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5701 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5702 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5703 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5704 /* Get points */ 5705 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5706 /* Get array */ 5707 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 5708 /* Get values */ 5709 for (f = 0; f < numFields; ++f) { 5710 const PetscInt **perms = NULL; 5711 const PetscScalar **flips = NULL; 5712 5713 if (!fieldActive[f]) { 5714 for (p = 0; p < numPoints*2; p += 2) { 5715 PetscInt fdof; 5716 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5717 offset += fdof; 5718 } 5719 continue; 5720 } 5721 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5722 switch (mode) { 5723 case INSERT_VALUES: 5724 for (p = 0; p < numPoints; p++) { 5725 const PetscInt point = points[2*p]; 5726 const PetscInt *perm = perms ? perms[p] : NULL; 5727 const PetscScalar *flip = flips ? flips[p] : NULL; 5728 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 5729 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array); 5730 } break; 5731 case INSERT_ALL_VALUES: 5732 for (p = 0; p < numPoints; p++) { 5733 const PetscInt point = points[2*p]; 5734 const PetscInt *perm = perms ? perms[p] : NULL; 5735 const PetscScalar *flip = flips ? flips[p] : NULL; 5736 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 5737 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array); 5738 } break; 5739 case INSERT_BC_VALUES: 5740 for (p = 0; p < numPoints; p++) { 5741 const PetscInt point = points[2*p]; 5742 const PetscInt *perm = perms ? perms[p] : NULL; 5743 const PetscScalar *flip = flips ? flips[p] : NULL; 5744 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 5745 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array); 5746 } break; 5747 case ADD_VALUES: 5748 for (p = 0; p < numPoints; p++) { 5749 const PetscInt point = points[2*p]; 5750 const PetscInt *perm = perms ? perms[p] : NULL; 5751 const PetscScalar *flip = flips ? flips[p] : NULL; 5752 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 5753 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array); 5754 } break; 5755 case ADD_ALL_VALUES: 5756 for (p = 0; p < numPoints; p++) { 5757 const PetscInt point = points[2*p]; 5758 const PetscInt *perm = perms ? perms[p] : NULL; 5759 const PetscScalar *flip = flips ? flips[p] : NULL; 5760 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 5761 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array); 5762 } break; 5763 default: 5764 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 5765 } 5766 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5767 } 5768 /* Cleanup points */ 5769 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5770 /* Cleanup array */ 5771 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 5772 PetscFunctionReturn(0); 5773 } 5774 5775 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 5776 { 5777 PetscMPIInt rank; 5778 PetscInt i, j; 5779 PetscErrorCode ierr; 5780 5781 PetscFunctionBegin; 5782 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr); 5783 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 5784 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 5785 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 5786 numCIndices = numCIndices ? numCIndices : numRIndices; 5787 if (!values) PetscFunctionReturn(0); 5788 for (i = 0; i < numRIndices; i++) { 5789 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 5790 for (j = 0; j < numCIndices; j++) { 5791 #if defined(PETSC_USE_COMPLEX) 5792 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 5793 #else 5794 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 5795 #endif 5796 } 5797 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 5798 } 5799 PetscFunctionReturn(0); 5800 } 5801 5802 /* 5803 DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 5804 5805 Input Parameters: 5806 + section - The section for this data layout 5807 . islocal - Is the section (and thus indices being requested) local or global? 5808 . point - The point contributing dofs with these indices 5809 . off - The global offset of this point 5810 . loff - The local offset of each field 5811 . setBC - The flag determining whether to include indices of bounsary values 5812 . perm - A permutation of the dofs on this point, or NULL 5813 - indperm - A permutation of the entire indices array, or NULL 5814 5815 Output Parameter: 5816 . indices - Indices for dofs on this point 5817 5818 Level: developer 5819 5820 Note: The indices could be local or global, depending on the value of 'off'. 5821 */ 5822 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 5823 { 5824 PetscInt dof; /* The number of unknowns on this point */ 5825 PetscInt cdof; /* The number of constraints on this point */ 5826 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5827 PetscInt cind = 0, k; 5828 PetscErrorCode ierr; 5829 5830 PetscFunctionBegin; 5831 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 5832 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5833 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5834 if (!cdof || setBC) { 5835 for (k = 0; k < dof; ++k) { 5836 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 5837 const PetscInt ind = indperm ? indperm[preind] : preind; 5838 5839 indices[ind] = off + k; 5840 } 5841 } else { 5842 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5843 for (k = 0; k < dof; ++k) { 5844 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 5845 const PetscInt ind = indperm ? indperm[preind] : preind; 5846 5847 if ((cind < cdof) && (k == cdofs[cind])) { 5848 /* Insert check for returning constrained indices */ 5849 indices[ind] = -(off+k+1); 5850 ++cind; 5851 } else { 5852 indices[ind] = off + k - (islocal ? 0 : cind); 5853 } 5854 } 5855 } 5856 *loff += dof; 5857 PetscFunctionReturn(0); 5858 } 5859 5860 /* 5861 DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 5862 5863 Input Parameters: 5864 + section - a section (global or local) 5865 - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 5866 . point - point within section 5867 . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 5868 . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 5869 . setBC - identify constrained (boundary condition) points via involution. 5870 . perms - perms[f][permsoff][:] is a permutation of dofs within each field 5871 . permsoff - offset 5872 - indperm - index permutation 5873 5874 Output Parameter: 5875 . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 5876 . indices - array to hold indices (as defined by section) of each dof associated with point 5877 5878 Notes: 5879 If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 5880 If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 5881 in the local vector. 5882 5883 If section is global and setBC=false, the indices for constrained points are negative (and their value is not 5884 significant). It is invalid to call with a global section and setBC=true. 5885 5886 Developer Note: 5887 The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 5888 in the future, global sections may have fields set, in which case we could pass the global section and obtain the 5889 offset could be obtained from the section instead of passing it explicitly as we do now. 5890 5891 Example: 5892 Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 5893 When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 5894 Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 5895 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. 5896 5897 Level: developer 5898 */ 5899 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[]) 5900 { 5901 PetscInt numFields, foff, f; 5902 PetscErrorCode ierr; 5903 5904 PetscFunctionBegin; 5905 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 5906 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5907 for (f = 0, foff = 0; f < numFields; ++f) { 5908 PetscInt fdof, cfdof; 5909 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5910 PetscInt cind = 0, b; 5911 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 5912 5913 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5914 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 5915 if (!cfdof || setBC) { 5916 for (b = 0; b < fdof; ++b) { 5917 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 5918 const PetscInt ind = indperm ? indperm[preind] : preind; 5919 5920 indices[ind] = off+foff+b; 5921 } 5922 } else { 5923 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5924 for (b = 0; b < fdof; ++b) { 5925 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 5926 const PetscInt ind = indperm ? indperm[preind] : preind; 5927 5928 if ((cind < cfdof) && (b == fcdofs[cind])) { 5929 indices[ind] = -(off+foff+b+1); 5930 ++cind; 5931 } else { 5932 indices[ind] = off + foff + b - (islocal ? 0 : cind); 5933 } 5934 } 5935 } 5936 foff += (setBC || islocal ? fdof : (fdof - cfdof)); 5937 foffs[f] += fdof; 5938 } 5939 PetscFunctionReturn(0); 5940 } 5941 5942 /* 5943 This version believes the globalSection offsets for each field, rather than just the point offset 5944 5945 . foffs - The offset into 'indices' for each field, since it is segregated by field 5946 5947 Notes: 5948 The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 5949 Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 5950 */ 5951 static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 5952 { 5953 PetscInt numFields, foff, f; 5954 PetscErrorCode ierr; 5955 5956 PetscFunctionBegin; 5957 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5958 for (f = 0; f < numFields; ++f) { 5959 PetscInt fdof, cfdof; 5960 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5961 PetscInt cind = 0, b; 5962 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 5963 5964 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5965 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 5966 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 5967 if (!cfdof) { 5968 for (b = 0; b < fdof; ++b) { 5969 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 5970 const PetscInt ind = indperm ? indperm[preind] : preind; 5971 5972 indices[ind] = foff+b; 5973 } 5974 } else { 5975 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5976 for (b = 0; b < fdof; ++b) { 5977 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 5978 const PetscInt ind = indperm ? indperm[preind] : preind; 5979 5980 if ((cind < cfdof) && (b == fcdofs[cind])) { 5981 indices[ind] = -(foff+b+1); 5982 ++cind; 5983 } else { 5984 indices[ind] = foff+b-cind; 5985 } 5986 } 5987 } 5988 foffs[f] += fdof; 5989 } 5990 PetscFunctionReturn(0); 5991 } 5992 5993 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) 5994 { 5995 Mat cMat; 5996 PetscSection aSec, cSec; 5997 IS aIS; 5998 PetscInt aStart = -1, aEnd = -1; 5999 const PetscInt *anchors; 6000 PetscInt numFields, f, p, q, newP = 0; 6001 PetscInt newNumPoints = 0, newNumIndices = 0; 6002 PetscInt *newPoints, *indices, *newIndices; 6003 PetscInt maxAnchor, maxDof; 6004 PetscInt newOffsets[32]; 6005 PetscInt *pointMatOffsets[32]; 6006 PetscInt *newPointOffsets[32]; 6007 PetscScalar *pointMat[32]; 6008 PetscScalar *newValues=NULL,*tmpValues; 6009 PetscBool anyConstrained = PETSC_FALSE; 6010 PetscErrorCode ierr; 6011 6012 PetscFunctionBegin; 6013 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6014 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6015 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6016 6017 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6018 /* if there are point-to-point constraints */ 6019 if (aSec) { 6020 ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr); 6021 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6022 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 6023 /* figure out how many points are going to be in the new element matrix 6024 * (we allow double counting, because it's all just going to be summed 6025 * into the global matrix anyway) */ 6026 for (p = 0; p < 2*numPoints; p+=2) { 6027 PetscInt b = points[p]; 6028 PetscInt bDof = 0, bSecDof; 6029 6030 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6031 if (!bSecDof) { 6032 continue; 6033 } 6034 if (b >= aStart && b < aEnd) { 6035 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 6036 } 6037 if (bDof) { 6038 /* this point is constrained */ 6039 /* it is going to be replaced by its anchors */ 6040 PetscInt bOff, q; 6041 6042 anyConstrained = PETSC_TRUE; 6043 newNumPoints += bDof; 6044 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 6045 for (q = 0; q < bDof; q++) { 6046 PetscInt a = anchors[bOff + q]; 6047 PetscInt aDof; 6048 6049 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6050 newNumIndices += aDof; 6051 for (f = 0; f < numFields; ++f) { 6052 PetscInt fDof; 6053 6054 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 6055 newOffsets[f+1] += fDof; 6056 } 6057 } 6058 } 6059 else { 6060 /* this point is not constrained */ 6061 newNumPoints++; 6062 newNumIndices += bSecDof; 6063 for (f = 0; f < numFields; ++f) { 6064 PetscInt fDof; 6065 6066 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6067 newOffsets[f+1] += fDof; 6068 } 6069 } 6070 } 6071 } 6072 if (!anyConstrained) { 6073 if (outNumPoints) *outNumPoints = 0; 6074 if (outNumIndices) *outNumIndices = 0; 6075 if (outPoints) *outPoints = NULL; 6076 if (outValues) *outValues = NULL; 6077 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6078 PetscFunctionReturn(0); 6079 } 6080 6081 if (outNumPoints) *outNumPoints = newNumPoints; 6082 if (outNumIndices) *outNumIndices = newNumIndices; 6083 6084 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6085 6086 if (!outPoints && !outValues) { 6087 if (offsets) { 6088 for (f = 0; f <= numFields; f++) { 6089 offsets[f] = newOffsets[f]; 6090 } 6091 } 6092 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6093 PetscFunctionReturn(0); 6094 } 6095 6096 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 6097 6098 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 6099 6100 /* workspaces */ 6101 if (numFields) { 6102 for (f = 0; f < numFields; f++) { 6103 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 6104 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6105 } 6106 } 6107 else { 6108 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 6109 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6110 } 6111 6112 /* get workspaces for the point-to-point matrices */ 6113 if (numFields) { 6114 PetscInt totalOffset, totalMatOffset; 6115 6116 for (p = 0; p < numPoints; p++) { 6117 PetscInt b = points[2*p]; 6118 PetscInt bDof = 0, bSecDof; 6119 6120 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6121 if (!bSecDof) { 6122 for (f = 0; f < numFields; f++) { 6123 newPointOffsets[f][p + 1] = 0; 6124 pointMatOffsets[f][p + 1] = 0; 6125 } 6126 continue; 6127 } 6128 if (b >= aStart && b < aEnd) { 6129 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6130 } 6131 if (bDof) { 6132 for (f = 0; f < numFields; f++) { 6133 PetscInt fDof, q, bOff, allFDof = 0; 6134 6135 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6136 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6137 for (q = 0; q < bDof; q++) { 6138 PetscInt a = anchors[bOff + q]; 6139 PetscInt aFDof; 6140 6141 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 6142 allFDof += aFDof; 6143 } 6144 newPointOffsets[f][p+1] = allFDof; 6145 pointMatOffsets[f][p+1] = fDof * allFDof; 6146 } 6147 } 6148 else { 6149 for (f = 0; f < numFields; f++) { 6150 PetscInt fDof; 6151 6152 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6153 newPointOffsets[f][p+1] = fDof; 6154 pointMatOffsets[f][p+1] = 0; 6155 } 6156 } 6157 } 6158 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 6159 newPointOffsets[f][0] = totalOffset; 6160 pointMatOffsets[f][0] = totalMatOffset; 6161 for (p = 0; p < numPoints; p++) { 6162 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6163 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6164 } 6165 totalOffset = newPointOffsets[f][numPoints]; 6166 totalMatOffset = pointMatOffsets[f][numPoints]; 6167 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 6168 } 6169 } 6170 else { 6171 for (p = 0; p < numPoints; p++) { 6172 PetscInt b = points[2*p]; 6173 PetscInt bDof = 0, bSecDof; 6174 6175 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6176 if (!bSecDof) { 6177 newPointOffsets[0][p + 1] = 0; 6178 pointMatOffsets[0][p + 1] = 0; 6179 continue; 6180 } 6181 if (b >= aStart && b < aEnd) { 6182 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6183 } 6184 if (bDof) { 6185 PetscInt bOff, q, allDof = 0; 6186 6187 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6188 for (q = 0; q < bDof; q++) { 6189 PetscInt a = anchors[bOff + q], aDof; 6190 6191 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 6192 allDof += aDof; 6193 } 6194 newPointOffsets[0][p+1] = allDof; 6195 pointMatOffsets[0][p+1] = bSecDof * allDof; 6196 } 6197 else { 6198 newPointOffsets[0][p+1] = bSecDof; 6199 pointMatOffsets[0][p+1] = 0; 6200 } 6201 } 6202 newPointOffsets[0][0] = 0; 6203 pointMatOffsets[0][0] = 0; 6204 for (p = 0; p < numPoints; p++) { 6205 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6206 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6207 } 6208 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 6209 } 6210 6211 /* output arrays */ 6212 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6213 6214 /* get the point-to-point matrices; construct newPoints */ 6215 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 6216 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6217 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 6218 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 6219 if (numFields) { 6220 for (p = 0, newP = 0; p < numPoints; p++) { 6221 PetscInt b = points[2*p]; 6222 PetscInt o = points[2*p+1]; 6223 PetscInt bDof = 0, bSecDof; 6224 6225 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6226 if (!bSecDof) { 6227 continue; 6228 } 6229 if (b >= aStart && b < aEnd) { 6230 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6231 } 6232 if (bDof) { 6233 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6234 6235 fStart[0] = 0; 6236 fEnd[0] = 0; 6237 for (f = 0; f < numFields; f++) { 6238 PetscInt fDof; 6239 6240 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 6241 fStart[f+1] = fStart[f] + fDof; 6242 fEnd[f+1] = fStart[f+1]; 6243 } 6244 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6245 ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 6246 6247 fAnchorStart[0] = 0; 6248 fAnchorEnd[0] = 0; 6249 for (f = 0; f < numFields; f++) { 6250 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 6251 6252 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 6253 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 6254 } 6255 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6256 for (q = 0; q < bDof; q++) { 6257 PetscInt a = anchors[bOff + q], aOff; 6258 6259 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6260 newPoints[2*(newP + q)] = a; 6261 newPoints[2*(newP + q) + 1] = 0; 6262 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 6263 ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 6264 } 6265 newP += bDof; 6266 6267 if (outValues) { 6268 /* get the point-to-point submatrix */ 6269 for (f = 0; f < numFields; f++) { 6270 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 6271 } 6272 } 6273 } 6274 else { 6275 newPoints[2 * newP] = b; 6276 newPoints[2 * newP + 1] = o; 6277 newP++; 6278 } 6279 } 6280 } else { 6281 for (p = 0; p < numPoints; p++) { 6282 PetscInt b = points[2*p]; 6283 PetscInt o = points[2*p+1]; 6284 PetscInt bDof = 0, bSecDof; 6285 6286 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6287 if (!bSecDof) { 6288 continue; 6289 } 6290 if (b >= aStart && b < aEnd) { 6291 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6292 } 6293 if (bDof) { 6294 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 6295 6296 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6297 ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 6298 6299 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 6300 for (q = 0; q < bDof; q++) { 6301 PetscInt a = anchors[bOff + q], aOff; 6302 6303 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6304 6305 newPoints[2*(newP + q)] = a; 6306 newPoints[2*(newP + q) + 1] = 0; 6307 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 6308 ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 6309 } 6310 newP += bDof; 6311 6312 /* get the point-to-point submatrix */ 6313 if (outValues) { 6314 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 6315 } 6316 } 6317 else { 6318 newPoints[2 * newP] = b; 6319 newPoints[2 * newP + 1] = o; 6320 newP++; 6321 } 6322 } 6323 } 6324 6325 if (outValues) { 6326 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 6327 ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr); 6328 /* multiply constraints on the right */ 6329 if (numFields) { 6330 for (f = 0; f < numFields; f++) { 6331 PetscInt oldOff = offsets[f]; 6332 6333 for (p = 0; p < numPoints; p++) { 6334 PetscInt cStart = newPointOffsets[f][p]; 6335 PetscInt b = points[2 * p]; 6336 PetscInt c, r, k; 6337 PetscInt dof; 6338 6339 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 6340 if (!dof) { 6341 continue; 6342 } 6343 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 6344 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 6345 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 6346 6347 for (r = 0; r < numIndices; r++) { 6348 for (c = 0; c < nCols; c++) { 6349 for (k = 0; k < dof; k++) { 6350 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 6351 } 6352 } 6353 } 6354 } 6355 else { 6356 /* copy this column as is */ 6357 for (r = 0; r < numIndices; r++) { 6358 for (c = 0; c < dof; c++) { 6359 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 6360 } 6361 } 6362 } 6363 oldOff += dof; 6364 } 6365 } 6366 } 6367 else { 6368 PetscInt oldOff = 0; 6369 for (p = 0; p < numPoints; p++) { 6370 PetscInt cStart = newPointOffsets[0][p]; 6371 PetscInt b = points[2 * p]; 6372 PetscInt c, r, k; 6373 PetscInt dof; 6374 6375 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 6376 if (!dof) { 6377 continue; 6378 } 6379 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 6380 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 6381 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 6382 6383 for (r = 0; r < numIndices; r++) { 6384 for (c = 0; c < nCols; c++) { 6385 for (k = 0; k < dof; k++) { 6386 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 6387 } 6388 } 6389 } 6390 } 6391 else { 6392 /* copy this column as is */ 6393 for (r = 0; r < numIndices; r++) { 6394 for (c = 0; c < dof; c++) { 6395 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 6396 } 6397 } 6398 } 6399 oldOff += dof; 6400 } 6401 } 6402 6403 if (multiplyLeft) { 6404 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 6405 ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr); 6406 /* multiply constraints transpose on the left */ 6407 if (numFields) { 6408 for (f = 0; f < numFields; f++) { 6409 PetscInt oldOff = offsets[f]; 6410 6411 for (p = 0; p < numPoints; p++) { 6412 PetscInt rStart = newPointOffsets[f][p]; 6413 PetscInt b = points[2 * p]; 6414 PetscInt c, r, k; 6415 PetscInt dof; 6416 6417 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 6418 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 6419 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 6420 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 6421 6422 for (r = 0; r < nRows; r++) { 6423 for (c = 0; c < newNumIndices; c++) { 6424 for (k = 0; k < dof; k++) { 6425 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 6426 } 6427 } 6428 } 6429 } 6430 else { 6431 /* copy this row as is */ 6432 for (r = 0; r < dof; r++) { 6433 for (c = 0; c < newNumIndices; c++) { 6434 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 6435 } 6436 } 6437 } 6438 oldOff += dof; 6439 } 6440 } 6441 } 6442 else { 6443 PetscInt oldOff = 0; 6444 6445 for (p = 0; p < numPoints; p++) { 6446 PetscInt rStart = newPointOffsets[0][p]; 6447 PetscInt b = points[2 * p]; 6448 PetscInt c, r, k; 6449 PetscInt dof; 6450 6451 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 6452 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 6453 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 6454 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 6455 6456 for (r = 0; r < nRows; r++) { 6457 for (c = 0; c < newNumIndices; c++) { 6458 for (k = 0; k < dof; k++) { 6459 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 6460 } 6461 } 6462 } 6463 } 6464 else { 6465 /* copy this row as is */ 6466 for (r = 0; r < dof; r++) { 6467 for (c = 0; c < newNumIndices; c++) { 6468 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 6469 } 6470 } 6471 } 6472 oldOff += dof; 6473 } 6474 } 6475 6476 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 6477 } 6478 else { 6479 newValues = tmpValues; 6480 } 6481 } 6482 6483 /* clean up */ 6484 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 6485 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 6486 6487 if (numFields) { 6488 for (f = 0; f < numFields; f++) { 6489 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 6490 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 6491 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6492 } 6493 } 6494 else { 6495 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 6496 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 6497 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6498 } 6499 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 6500 6501 /* output */ 6502 if (outPoints) { 6503 *outPoints = newPoints; 6504 } 6505 else { 6506 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6507 } 6508 if (outValues) { 6509 *outValues = newValues; 6510 } 6511 for (f = 0; f <= numFields; f++) { 6512 offsets[f] = newOffsets[f]; 6513 } 6514 PetscFunctionReturn(0); 6515 } 6516 6517 /*@C 6518 DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 6519 6520 Not collective 6521 6522 Input Parameters: 6523 + dm - The DM 6524 . section - The PetscSection describing the points (a local section) 6525 . idxSection - The PetscSection from which to obtain indices (may be local or global) 6526 . point - The point defining the closure 6527 - useClPerm - Use the closure point permutation if available 6528 6529 Output Parameters: 6530 + numIndices - The number of dof indices in the closure of point with the input sections 6531 . indices - The dof indices 6532 . outOffsets - Array to write the field offsets into, or NULL 6533 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 6534 6535 Notes: 6536 Must call DMPlexRestoreClosureIndices() to free allocated memory 6537 6538 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 6539 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 6540 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 6541 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 6542 indices (with the above semantics) are implied. 6543 6544 Level: advanced 6545 6546 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 6547 @*/ 6548 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 6549 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 6550 { 6551 /* Closure ordering */ 6552 PetscSection clSection; 6553 IS clPoints; 6554 const PetscInt *clp; 6555 PetscInt *points; 6556 const PetscInt *clperm = NULL; 6557 /* Dof permutation and sign flips */ 6558 const PetscInt **perms[32] = {NULL}; 6559 const PetscScalar **flips[32] = {NULL}; 6560 PetscScalar *valCopy = NULL; 6561 /* Hanging node constraints */ 6562 PetscInt *pointsC = NULL; 6563 PetscScalar *valuesC = NULL; 6564 PetscInt NclC, NiC; 6565 6566 PetscInt *idx; 6567 PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 6568 PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 6569 PetscErrorCode ierr; 6570 6571 PetscFunctionBeginHot; 6572 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6573 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6574 PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 6575 if (numIndices) PetscValidPointer(numIndices, 6); 6576 if (indices) PetscValidPointer(indices, 7); 6577 if (outOffsets) PetscValidPointer(outOffsets, 8); 6578 if (values) PetscValidPointer(values, 9); 6579 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 6580 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 6581 ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 6582 /* 1) Get points in closure */ 6583 ierr = DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 6584 if (useClPerm) { 6585 PetscInt depth, clsize; 6586 ierr = DMPlexGetPointDepth(dm, point, &depth);CHKERRQ(ierr); 6587 for (clsize=0,p=0; p<Ncl; p++) { 6588 PetscInt dof; 6589 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 6590 clsize += dof; 6591 } 6592 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 6593 } 6594 /* 2) Get number of indices on these points and field offsets from section */ 6595 for (p = 0; p < Ncl*2; p += 2) { 6596 PetscInt dof, fdof; 6597 6598 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6599 for (f = 0; f < Nf; ++f) { 6600 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6601 offsets[f+1] += fdof; 6602 } 6603 Ni += dof; 6604 } 6605 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 6606 if (Nf && offsets[Nf] != Ni) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni); 6607 /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 6608 for (f = 0; f < PetscMax(1, Nf); ++f) { 6609 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 6610 else {ierr = PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 6611 /* may need to apply sign changes to the element matrix */ 6612 if (values && flips[f]) { 6613 PetscInt foffset = offsets[f]; 6614 6615 for (p = 0; p < Ncl; ++p) { 6616 PetscInt pnt = points[2*p], fdof; 6617 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 6618 6619 if (!Nf) {ierr = PetscSectionGetDof(section, pnt, &fdof);CHKERRQ(ierr);} 6620 else {ierr = PetscSectionGetFieldDof(section, pnt, f, &fdof);CHKERRQ(ierr);} 6621 if (flip) { 6622 PetscInt i, j, k; 6623 6624 if (!valCopy) { 6625 ierr = DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr); 6626 for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 6627 *values = valCopy; 6628 } 6629 for (i = 0; i < fdof; ++i) { 6630 PetscScalar fval = flip[i]; 6631 6632 for (k = 0; k < Ni; ++k) { 6633 valCopy[Ni * (foffset + i) + k] *= fval; 6634 valCopy[Ni * k + (foffset + i)] *= fval; 6635 } 6636 } 6637 } 6638 foffset += fdof; 6639 } 6640 } 6641 } 6642 /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 6643 ierr = DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 6644 if (NclC) { 6645 if (valCopy) {ierr = DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);} 6646 for (f = 0; f < PetscMax(1, Nf); ++f) { 6647 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 6648 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 6649 } 6650 for (f = 0; f < PetscMax(1, Nf); ++f) { 6651 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 6652 else {ierr = PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 6653 } 6654 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 6655 Ncl = NclC; 6656 Ni = NiC; 6657 points = pointsC; 6658 if (values) *values = valuesC; 6659 } 6660 /* 5) Calculate indices */ 6661 ierr = DMGetWorkArray(dm, Ni, MPIU_INT, &idx);CHKERRQ(ierr); 6662 if (Nf) { 6663 PetscInt idxOff; 6664 PetscBool useFieldOffsets; 6665 6666 if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 6667 ierr = PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets);CHKERRQ(ierr); 6668 if (useFieldOffsets) { 6669 for (p = 0; p < Ncl; ++p) { 6670 const PetscInt pnt = points[p*2]; 6671 6672 ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx);CHKERRQ(ierr); 6673 } 6674 } else { 6675 for (p = 0; p < Ncl; ++p) { 6676 const PetscInt pnt = points[p*2]; 6677 6678 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 6679 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 6680 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 6681 * global section. */ 6682 ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx);CHKERRQ(ierr); 6683 } 6684 } 6685 } else { 6686 PetscInt off = 0, idxOff; 6687 6688 for (p = 0; p < Ncl; ++p) { 6689 const PetscInt pnt = points[p*2]; 6690 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 6691 6692 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 6693 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 6694 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 6695 ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx);CHKERRQ(ierr); 6696 } 6697 } 6698 /* 6) Cleanup */ 6699 for (f = 0; f < PetscMax(1, Nf); ++f) { 6700 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 6701 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 6702 } 6703 if (NclC) { 6704 ierr = DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC);CHKERRQ(ierr); 6705 } else { 6706 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 6707 } 6708 6709 if (numIndices) *numIndices = Ni; 6710 if (indices) *indices = idx; 6711 PetscFunctionReturn(0); 6712 } 6713 6714 /*@C 6715 DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 6716 6717 Not collective 6718 6719 Input Parameters: 6720 + dm - The DM 6721 . section - The PetscSection describing the points (a local section) 6722 . idxSection - The PetscSection from which to obtain indices (may be local or global) 6723 . point - The point defining the closure 6724 - useClPerm - Use the closure point permutation if available 6725 6726 Output Parameters: 6727 + numIndices - The number of dof indices in the closure of point with the input sections 6728 . indices - The dof indices 6729 . outOffsets - Array to write the field offsets into, or NULL 6730 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 6731 6732 Notes: 6733 If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 6734 6735 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 6736 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 6737 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 6738 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 6739 indices (with the above semantics) are implied. 6740 6741 Level: advanced 6742 6743 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 6744 @*/ 6745 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 6746 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 6747 { 6748 PetscErrorCode ierr; 6749 6750 PetscFunctionBegin; 6751 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6752 PetscValidPointer(indices, 7); 6753 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 6754 PetscFunctionReturn(0); 6755 } 6756 6757 /*@C 6758 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 6759 6760 Not collective 6761 6762 Input Parameters: 6763 + dm - The DM 6764 . section - The section describing the layout in v, or NULL to use the default section 6765 . globalSection - The section describing the layout in v, or NULL to use the default global section 6766 . A - The matrix 6767 . point - The point in the DM 6768 . values - The array of values 6769 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 6770 6771 Fortran Notes: 6772 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6773 6774 Level: intermediate 6775 6776 .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 6777 @*/ 6778 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 6779 { 6780 DM_Plex *mesh = (DM_Plex*) dm->data; 6781 PetscInt *indices; 6782 PetscInt numIndices; 6783 const PetscScalar *valuesOrig = values; 6784 PetscErrorCode ierr; 6785 6786 PetscFunctionBegin; 6787 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6788 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6789 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6790 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 6791 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 6792 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 6793 6794 ierr = DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 6795 6796 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 6797 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 6798 if (ierr) { 6799 PetscMPIInt rank; 6800 PetscErrorCode ierr2; 6801 6802 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 6803 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 6804 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 6805 ierr2 = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 6806 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 6807 CHKERRQ(ierr); 6808 } 6809 if (mesh->printFEM > 1) { 6810 PetscInt i; 6811 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 6812 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 6813 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6814 } 6815 6816 ierr = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 6817 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 6818 PetscFunctionReturn(0); 6819 } 6820 6821 /*@C 6822 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 6823 6824 Not collective 6825 6826 Input Parameters: 6827 + dmRow - The DM for the row fields 6828 . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 6829 . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 6830 . dmCol - The DM for the column fields 6831 . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 6832 . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 6833 . A - The matrix 6834 . point - The point in the DMs 6835 . values - The array of values 6836 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 6837 6838 Level: intermediate 6839 6840 .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 6841 @*/ 6842 PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 6843 { 6844 DM_Plex *mesh = (DM_Plex*) dmRow->data; 6845 PetscInt *indicesRow, *indicesCol; 6846 PetscInt numIndicesRow, numIndicesCol; 6847 const PetscScalar *valuesOrig = values; 6848 PetscErrorCode ierr; 6849 6850 PetscFunctionBegin; 6851 PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 6852 if (!sectionRow) {ierr = DMGetLocalSection(dmRow, §ionRow);CHKERRQ(ierr);} 6853 PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 6854 if (!globalSectionRow) {ierr = DMGetGlobalSection(dmRow, &globalSectionRow);CHKERRQ(ierr);} 6855 PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 6856 PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 6857 if (!sectionCol) {ierr = DMGetLocalSection(dmCol, §ionCol);CHKERRQ(ierr);} 6858 PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 6859 if (!globalSectionCol) {ierr = DMGetGlobalSection(dmCol, &globalSectionCol);CHKERRQ(ierr);} 6860 PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 6861 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 6862 6863 ierr = DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 6864 ierr = DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 6865 6866 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr);} 6867 ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 6868 if (ierr) { 6869 PetscMPIInt rank; 6870 PetscErrorCode ierr2; 6871 6872 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 6873 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 6874 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr2); 6875 ierr2 = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 6876 ierr2 = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 6877 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 6878 CHKERRQ(ierr); 6879 } 6880 6881 ierr = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 6882 ierr = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 6883 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 6884 PetscFunctionReturn(0); 6885 } 6886 6887 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 6888 { 6889 DM_Plex *mesh = (DM_Plex*) dmf->data; 6890 PetscInt *fpoints = NULL, *ftotpoints = NULL; 6891 PetscInt *cpoints = NULL; 6892 PetscInt *findices, *cindices; 6893 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 6894 PetscInt foffsets[32], coffsets[32]; 6895 DMPolytopeType ct; 6896 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 6897 PetscErrorCode ierr; 6898 6899 PetscFunctionBegin; 6900 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 6901 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 6902 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 6903 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 6904 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 6905 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 6906 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 6907 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 6908 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 6909 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 6910 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 6911 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 6912 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6913 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 6914 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 6915 /* Column indices */ 6916 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 6917 maxFPoints = numCPoints; 6918 /* Compress out points not in the section */ 6919 /* TODO: Squeeze out points with 0 dof as well */ 6920 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 6921 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 6922 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 6923 cpoints[q*2] = cpoints[p]; 6924 cpoints[q*2+1] = cpoints[p+1]; 6925 ++q; 6926 } 6927 } 6928 numCPoints = q; 6929 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 6930 PetscInt fdof; 6931 6932 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 6933 if (!dof) continue; 6934 for (f = 0; f < numFields; ++f) { 6935 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 6936 coffsets[f+1] += fdof; 6937 } 6938 numCIndices += dof; 6939 } 6940 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 6941 /* Row indices */ 6942 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 6943 { 6944 DMPlexCellRefiner cr; 6945 ierr = DMPlexCellRefinerCreate(dmc, &cr);CHKERRQ(ierr); 6946 ierr = DMPlexCellRefinerGetAffineTransforms(cr, ct, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 6947 ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 6948 } 6949 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6950 for (r = 0, q = 0; r < numSubcells; ++r) { 6951 /* TODO Map from coarse to fine cells */ 6952 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6953 /* Compress out points not in the section */ 6954 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 6955 for (p = 0; p < numFPoints*2; p += 2) { 6956 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 6957 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 6958 if (!dof) continue; 6959 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 6960 if (s < q) continue; 6961 ftotpoints[q*2] = fpoints[p]; 6962 ftotpoints[q*2+1] = fpoints[p+1]; 6963 ++q; 6964 } 6965 } 6966 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6967 } 6968 numFPoints = q; 6969 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 6970 PetscInt fdof; 6971 6972 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 6973 if (!dof) continue; 6974 for (f = 0; f < numFields; ++f) { 6975 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 6976 foffsets[f+1] += fdof; 6977 } 6978 numFIndices += dof; 6979 } 6980 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 6981 6982 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 6983 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 6984 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 6985 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 6986 if (numFields) { 6987 const PetscInt **permsF[32] = {NULL}; 6988 const PetscInt **permsC[32] = {NULL}; 6989 6990 for (f = 0; f < numFields; f++) { 6991 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 6992 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6993 } 6994 for (p = 0; p < numFPoints; p++) { 6995 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6996 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 6997 } 6998 for (p = 0; p < numCPoints; p++) { 6999 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7000 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7001 } 7002 for (f = 0; f < numFields; f++) { 7003 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7004 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7005 } 7006 } else { 7007 const PetscInt **permsF = NULL; 7008 const PetscInt **permsC = NULL; 7009 7010 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7011 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7012 for (p = 0, off = 0; p < numFPoints; p++) { 7013 const PetscInt *perm = permsF ? permsF[p] : NULL; 7014 7015 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7016 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7017 } 7018 for (p = 0, off = 0; p < numCPoints; p++) { 7019 const PetscInt *perm = permsC ? permsC[p] : NULL; 7020 7021 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7022 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7023 } 7024 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7025 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7026 } 7027 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 7028 /* TODO: flips */ 7029 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7030 if (ierr) { 7031 PetscMPIInt rank; 7032 PetscErrorCode ierr2; 7033 7034 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7035 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7036 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 7037 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 7038 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 7039 CHKERRQ(ierr); 7040 } 7041 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7042 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7043 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7044 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7045 PetscFunctionReturn(0); 7046 } 7047 7048 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 7049 { 7050 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7051 PetscInt *cpoints = NULL; 7052 PetscInt foffsets[32], coffsets[32]; 7053 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7054 DMPolytopeType ct; 7055 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7056 PetscErrorCode ierr; 7057 7058 PetscFunctionBegin; 7059 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7060 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7061 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7062 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7063 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7064 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7065 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7066 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7067 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7068 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7069 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7070 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7071 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7072 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7073 /* Column indices */ 7074 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7075 maxFPoints = numCPoints; 7076 /* Compress out points not in the section */ 7077 /* TODO: Squeeze out points with 0 dof as well */ 7078 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7079 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7080 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7081 cpoints[q*2] = cpoints[p]; 7082 cpoints[q*2+1] = cpoints[p+1]; 7083 ++q; 7084 } 7085 } 7086 numCPoints = q; 7087 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7088 PetscInt fdof; 7089 7090 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7091 if (!dof) continue; 7092 for (f = 0; f < numFields; ++f) { 7093 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7094 coffsets[f+1] += fdof; 7095 } 7096 numCIndices += dof; 7097 } 7098 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7099 /* Row indices */ 7100 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7101 { 7102 DMPlexCellRefiner cr; 7103 ierr = DMPlexCellRefinerCreate(dmc, &cr);CHKERRQ(ierr); 7104 ierr = DMPlexCellRefinerGetAffineTransforms(cr, ct, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 7105 ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 7106 } 7107 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7108 for (r = 0, q = 0; r < numSubcells; ++r) { 7109 /* TODO Map from coarse to fine cells */ 7110 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7111 /* Compress out points not in the section */ 7112 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7113 for (p = 0; p < numFPoints*2; p += 2) { 7114 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7115 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7116 if (!dof) continue; 7117 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7118 if (s < q) continue; 7119 ftotpoints[q*2] = fpoints[p]; 7120 ftotpoints[q*2+1] = fpoints[p+1]; 7121 ++q; 7122 } 7123 } 7124 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7125 } 7126 numFPoints = q; 7127 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7128 PetscInt fdof; 7129 7130 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7131 if (!dof) continue; 7132 for (f = 0; f < numFields; ++f) { 7133 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7134 foffsets[f+1] += fdof; 7135 } 7136 numFIndices += dof; 7137 } 7138 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7139 7140 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7141 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7142 if (numFields) { 7143 const PetscInt **permsF[32] = {NULL}; 7144 const PetscInt **permsC[32] = {NULL}; 7145 7146 for (f = 0; f < numFields; f++) { 7147 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7148 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7149 } 7150 for (p = 0; p < numFPoints; p++) { 7151 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7152 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7153 } 7154 for (p = 0; p < numCPoints; p++) { 7155 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7156 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7157 } 7158 for (f = 0; f < numFields; f++) { 7159 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7160 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7161 } 7162 } else { 7163 const PetscInt **permsF = NULL; 7164 const PetscInt **permsC = NULL; 7165 7166 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7167 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7168 for (p = 0, off = 0; p < numFPoints; p++) { 7169 const PetscInt *perm = permsF ? permsF[p] : NULL; 7170 7171 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7172 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7173 } 7174 for (p = 0, off = 0; p < numCPoints; p++) { 7175 const PetscInt *perm = permsC ? permsC[p] : NULL; 7176 7177 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7178 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7179 } 7180 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7181 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7182 } 7183 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7184 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7185 PetscFunctionReturn(0); 7186 } 7187 7188 /*@C 7189 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 7190 7191 Input Parameter: 7192 . dm - The DMPlex object 7193 7194 Output Parameter: 7195 . cellHeight - The height of a cell 7196 7197 Level: developer 7198 7199 .seealso DMPlexSetVTKCellHeight() 7200 @*/ 7201 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7202 { 7203 DM_Plex *mesh = (DM_Plex*) dm->data; 7204 7205 PetscFunctionBegin; 7206 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7207 PetscValidPointer(cellHeight, 2); 7208 *cellHeight = mesh->vtkCellHeight; 7209 PetscFunctionReturn(0); 7210 } 7211 7212 /*@C 7213 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 7214 7215 Input Parameters: 7216 + dm - The DMPlex object 7217 - cellHeight - The height of a cell 7218 7219 Level: developer 7220 7221 .seealso DMPlexGetVTKCellHeight() 7222 @*/ 7223 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7224 { 7225 DM_Plex *mesh = (DM_Plex*) dm->data; 7226 7227 PetscFunctionBegin; 7228 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7229 mesh->vtkCellHeight = cellHeight; 7230 PetscFunctionReturn(0); 7231 } 7232 7233 /*@ 7234 DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 7235 7236 Input Parameter: 7237 . dm - The DMPlex object 7238 7239 Output Parameters: 7240 + gcStart - The first ghost cell, or NULL 7241 - gcEnd - The upper bound on ghost cells, or NULL 7242 7243 Level: advanced 7244 7245 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 7246 @*/ 7247 PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 7248 { 7249 DMLabel ctLabel; 7250 PetscErrorCode ierr; 7251 7252 PetscFunctionBegin; 7253 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7254 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 7255 ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr); 7256 PetscFunctionReturn(0); 7257 } 7258 7259 /* We can easily have a form that takes an IS instead */ 7260 PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 7261 { 7262 PetscSection section, globalSection; 7263 PetscInt *numbers, p; 7264 PetscErrorCode ierr; 7265 7266 PetscFunctionBegin; 7267 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7268 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 7269 for (p = pStart; p < pEnd; ++p) { 7270 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 7271 } 7272 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 7273 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7274 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 7275 for (p = pStart; p < pEnd; ++p) { 7276 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 7277 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 7278 else numbers[p-pStart] += shift; 7279 } 7280 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 7281 if (globalSize) { 7282 PetscLayout layout; 7283 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 7284 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 7285 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 7286 } 7287 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7288 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 7289 PetscFunctionReturn(0); 7290 } 7291 7292 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 7293 { 7294 PetscInt cellHeight, cStart, cEnd; 7295 PetscErrorCode ierr; 7296 7297 PetscFunctionBegin; 7298 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 7299 if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 7300 else {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 7301 ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 7302 PetscFunctionReturn(0); 7303 } 7304 7305 /*@ 7306 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 7307 7308 Input Parameter: 7309 . dm - The DMPlex object 7310 7311 Output Parameter: 7312 . globalCellNumbers - Global cell numbers for all cells on this process 7313 7314 Level: developer 7315 7316 .seealso DMPlexGetVertexNumbering() 7317 @*/ 7318 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 7319 { 7320 DM_Plex *mesh = (DM_Plex*) dm->data; 7321 PetscErrorCode ierr; 7322 7323 PetscFunctionBegin; 7324 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7325 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 7326 *globalCellNumbers = mesh->globalCellNumbers; 7327 PetscFunctionReturn(0); 7328 } 7329 7330 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 7331 { 7332 PetscInt vStart, vEnd; 7333 PetscErrorCode ierr; 7334 7335 PetscFunctionBegin; 7336 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7337 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7338 ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 7339 PetscFunctionReturn(0); 7340 } 7341 7342 /*@ 7343 DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 7344 7345 Input Parameter: 7346 . dm - The DMPlex object 7347 7348 Output Parameter: 7349 . globalVertexNumbers - Global vertex numbers for all vertices on this process 7350 7351 Level: developer 7352 7353 .seealso DMPlexGetCellNumbering() 7354 @*/ 7355 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 7356 { 7357 DM_Plex *mesh = (DM_Plex*) dm->data; 7358 PetscErrorCode ierr; 7359 7360 PetscFunctionBegin; 7361 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7362 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 7363 *globalVertexNumbers = mesh->globalVertexNumbers; 7364 PetscFunctionReturn(0); 7365 } 7366 7367 /*@ 7368 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 7369 7370 Input Parameter: 7371 . dm - The DMPlex object 7372 7373 Output Parameter: 7374 . globalPointNumbers - Global numbers for all points on this process 7375 7376 Level: developer 7377 7378 .seealso DMPlexGetCellNumbering() 7379 @*/ 7380 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 7381 { 7382 IS nums[4]; 7383 PetscInt depths[4], gdepths[4], starts[4]; 7384 PetscInt depth, d, shift = 0; 7385 PetscErrorCode ierr; 7386 7387 PetscFunctionBegin; 7388 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7389 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7390 /* For unstratified meshes use dim instead of depth */ 7391 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 7392 for (d = 0; d <= depth; ++d) { 7393 PetscInt end; 7394 7395 depths[d] = depth-d; 7396 ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 7397 if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 7398 } 7399 ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 7400 ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 7401 for (d = 0; d <= depth; ++d) { 7402 if (starts[d] >= 0 && depths[d] != gdepths[d]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 7403 } 7404 for (d = 0; d <= depth; ++d) { 7405 PetscInt pStart, pEnd, gsize; 7406 7407 ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 7408 ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 7409 shift += gsize; 7410 } 7411 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 7412 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 7413 PetscFunctionReturn(0); 7414 } 7415 7416 7417 /*@ 7418 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 7419 7420 Input Parameter: 7421 . dm - The DMPlex object 7422 7423 Output Parameter: 7424 . ranks - The rank field 7425 7426 Options Database Keys: 7427 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 7428 7429 Level: intermediate 7430 7431 .seealso: DMView() 7432 @*/ 7433 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 7434 { 7435 DM rdm; 7436 PetscFE fe; 7437 PetscScalar *r; 7438 PetscMPIInt rank; 7439 DMPolytopeType ct; 7440 PetscInt dim, cStart, cEnd, c; 7441 PetscBool simplex; 7442 PetscErrorCode ierr; 7443 7444 PetscFunctionBeginUser; 7445 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7446 PetscValidPointer(ranks, 2); 7447 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 7448 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 7449 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 7450 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7451 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 7452 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 7453 ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 7454 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 7455 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 7456 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 7457 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 7458 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 7459 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 7460 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 7461 for (c = cStart; c < cEnd; ++c) { 7462 PetscScalar *lr; 7463 7464 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 7465 if (lr) *lr = rank; 7466 } 7467 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 7468 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 7469 PetscFunctionReturn(0); 7470 } 7471 7472 /*@ 7473 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 7474 7475 Input Parameters: 7476 + dm - The DMPlex 7477 - label - The DMLabel 7478 7479 Output Parameter: 7480 . val - The label value field 7481 7482 Options Database Keys: 7483 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 7484 7485 Level: intermediate 7486 7487 .seealso: DMView() 7488 @*/ 7489 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 7490 { 7491 DM rdm; 7492 PetscFE fe; 7493 PetscScalar *v; 7494 PetscInt dim, cStart, cEnd, c; 7495 PetscErrorCode ierr; 7496 7497 PetscFunctionBeginUser; 7498 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7499 PetscValidPointer(label, 2); 7500 PetscValidPointer(val, 3); 7501 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 7502 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 7503 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 7504 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 7505 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 7506 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 7507 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 7508 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7509 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 7510 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 7511 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 7512 for (c = cStart; c < cEnd; ++c) { 7513 PetscScalar *lv; 7514 PetscInt cval; 7515 7516 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 7517 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 7518 *lv = cval; 7519 } 7520 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 7521 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 7522 PetscFunctionReturn(0); 7523 } 7524 7525 /*@ 7526 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 7527 7528 Input Parameter: 7529 . dm - The DMPlex object 7530 7531 Notes: 7532 This is a useful diagnostic when creating meshes programmatically. 7533 7534 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7535 7536 Level: developer 7537 7538 .seealso: DMCreate(), DMSetFromOptions() 7539 @*/ 7540 PetscErrorCode DMPlexCheckSymmetry(DM dm) 7541 { 7542 PetscSection coneSection, supportSection; 7543 const PetscInt *cone, *support; 7544 PetscInt coneSize, c, supportSize, s; 7545 PetscInt pStart, pEnd, p, pp, csize, ssize; 7546 PetscBool storagecheck = PETSC_TRUE; 7547 PetscErrorCode ierr; 7548 7549 PetscFunctionBegin; 7550 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7551 ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr); 7552 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 7553 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 7554 /* Check that point p is found in the support of its cone points, and vice versa */ 7555 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7556 for (p = pStart; p < pEnd; ++p) { 7557 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 7558 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 7559 for (c = 0; c < coneSize; ++c) { 7560 PetscBool dup = PETSC_FALSE; 7561 PetscInt d; 7562 for (d = c-1; d >= 0; --d) { 7563 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 7564 } 7565 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 7566 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 7567 for (s = 0; s < supportSize; ++s) { 7568 if (support[s] == p) break; 7569 } 7570 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 7571 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 7572 for (s = 0; s < coneSize; ++s) { 7573 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 7574 } 7575 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7576 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 7577 for (s = 0; s < supportSize; ++s) { 7578 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 7579 } 7580 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7581 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 7582 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 7583 } 7584 } 7585 ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 7586 if (p != pp) { storagecheck = PETSC_FALSE; continue; } 7587 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 7588 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 7589 for (s = 0; s < supportSize; ++s) { 7590 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 7591 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 7592 for (c = 0; c < coneSize; ++c) { 7593 ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 7594 if (cone[c] != pp) { c = 0; break; } 7595 if (cone[c] == p) break; 7596 } 7597 if (c >= coneSize) { 7598 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 7599 for (c = 0; c < supportSize; ++c) { 7600 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 7601 } 7602 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7603 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 7604 for (c = 0; c < coneSize; ++c) { 7605 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 7606 } 7607 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7608 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 7609 } 7610 } 7611 } 7612 if (storagecheck) { 7613 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 7614 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 7615 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 7616 } 7617 PetscFunctionReturn(0); 7618 } 7619 7620 /* 7621 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. 7622 */ 7623 static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 7624 { 7625 DMPolytopeType cct; 7626 PetscInt ptpoints[4]; 7627 const PetscInt *cone, *ccone, *ptcone; 7628 PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 7629 PetscErrorCode ierr; 7630 7631 PetscFunctionBegin; 7632 *unsplit = 0; 7633 switch (ct) { 7634 case DM_POLYTOPE_SEG_PRISM_TENSOR: 7635 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 7636 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7637 for (cp = 0; cp < coneSize; ++cp) { 7638 ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr); 7639 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 7640 } 7641 break; 7642 case DM_POLYTOPE_TRI_PRISM_TENSOR: 7643 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 7644 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 7645 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7646 for (cp = 0; cp < coneSize; ++cp) { 7647 ierr = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr); 7648 ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr); 7649 for (ccp = 0; ccp < cconeSize; ++ccp) { 7650 ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr); 7651 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 7652 PetscInt p; 7653 for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 7654 if (p == npt) ptpoints[npt++] = ccone[ccp]; 7655 } 7656 } 7657 } 7658 break; 7659 default: break; 7660 } 7661 for (pt = 0; pt < npt; ++pt) { 7662 ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr); 7663 if (ptcone[0] == ptcone[1]) ++(*unsplit); 7664 } 7665 PetscFunctionReturn(0); 7666 } 7667 7668 /*@ 7669 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 7670 7671 Input Parameters: 7672 + dm - The DMPlex object 7673 - cellHeight - Normally 0 7674 7675 Notes: 7676 This is a useful diagnostic when creating meshes programmatically. 7677 Currently applicable only to homogeneous simplex or tensor meshes. 7678 7679 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7680 7681 Level: developer 7682 7683 .seealso: DMCreate(), DMSetFromOptions() 7684 @*/ 7685 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 7686 { 7687 DMPlexInterpolatedFlag interp; 7688 DMPolytopeType ct; 7689 PetscInt vStart, vEnd, cStart, cEnd, c; 7690 PetscErrorCode ierr; 7691 7692 PetscFunctionBegin; 7693 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7694 ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr); 7695 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 7696 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7697 for (c = cStart; c < cEnd; ++c) { 7698 PetscInt *closure = NULL; 7699 PetscInt coneSize, closureSize, cl, Nv = 0; 7700 7701 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 7702 if ((PetscInt) ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c); 7703 if (ct == DM_POLYTOPE_UNKNOWN) continue; 7704 if (interp == DMPLEX_INTERPOLATED_FULL) { 7705 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7706 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)); 7707 } 7708 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7709 for (cl = 0; cl < closureSize*2; cl += 2) { 7710 const PetscInt p = closure[cl]; 7711 if ((p >= vStart) && (p < vEnd)) ++Nv; 7712 } 7713 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7714 /* Special Case: Tensor faces with identified vertices */ 7715 if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 7716 PetscInt unsplit; 7717 7718 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 7719 if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 7720 } 7721 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)); 7722 } 7723 PetscFunctionReturn(0); 7724 } 7725 7726 /*@ 7727 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 7728 7729 Not Collective 7730 7731 Input Parameters: 7732 + dm - The DMPlex object 7733 - cellHeight - Normally 0 7734 7735 Notes: 7736 This is a useful diagnostic when creating meshes programmatically. 7737 This routine is only relevant for meshes that are fully interpolated across all ranks. 7738 It will error out if a partially interpolated mesh is given on some rank. 7739 It will do nothing for locally uninterpolated mesh (as there is nothing to check). 7740 7741 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7742 7743 Level: developer 7744 7745 .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 7746 @*/ 7747 PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 7748 { 7749 PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 7750 PetscErrorCode ierr; 7751 DMPlexInterpolatedFlag interpEnum; 7752 7753 PetscFunctionBegin; 7754 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7755 ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr); 7756 if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 7757 if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 7758 PetscMPIInt rank; 7759 MPI_Comm comm; 7760 7761 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 7762 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 7763 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 7764 } 7765 7766 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 7767 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7768 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7769 for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 7770 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 7771 for (c = cStart; c < cEnd; ++c) { 7772 const PetscInt *cone, *ornt, *faceSizes, *faces; 7773 const DMPolytopeType *faceTypes; 7774 DMPolytopeType ct; 7775 PetscInt numFaces, coneSize, f; 7776 PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 7777 7778 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 7779 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 7780 if (unsplit) continue; 7781 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7782 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 7783 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 7784 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7785 for (cl = 0; cl < closureSize*2; cl += 2) { 7786 const PetscInt p = closure[cl]; 7787 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 7788 } 7789 ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 7790 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); 7791 for (f = 0; f < numFaces; ++f) { 7792 DMPolytopeType fct; 7793 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 7794 7795 ierr = DMPlexGetCellType(dm, cone[f], &fct);CHKERRQ(ierr); 7796 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 7797 for (cl = 0; cl < fclosureSize*2; cl += 2) { 7798 const PetscInt p = fclosure[cl]; 7799 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 7800 } 7801 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]); 7802 for (v = 0; v < fnumCorners; ++v) { 7803 if (fclosure[v] != faces[fOff+v]) SETERRQ8(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D of type %s (cone idx %d) of cell %D of type %s vertex %D, %D != %D", cone[f], DMPolytopeTypes[fct], f, c, DMPolytopeTypes[ct], v, fclosure[v], faces[fOff+v]); 7804 } 7805 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 7806 fOff += faceSizes[f]; 7807 } 7808 ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 7809 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7810 } 7811 } 7812 PetscFunctionReturn(0); 7813 } 7814 7815 /*@ 7816 DMPlexCheckGeometry - Check the geometry of mesh cells 7817 7818 Input Parameter: 7819 . dm - The DMPlex object 7820 7821 Notes: 7822 This is a useful diagnostic when creating meshes programmatically. 7823 7824 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7825 7826 Level: developer 7827 7828 .seealso: DMCreate(), DMSetFromOptions() 7829 @*/ 7830 PetscErrorCode DMPlexCheckGeometry(DM dm) 7831 { 7832 Vec coordinates; 7833 PetscReal detJ, J[9], refVol = 1.0; 7834 PetscReal vol; 7835 PetscBool periodic; 7836 PetscInt dim, depth, dE, d, cStart, cEnd, c; 7837 PetscErrorCode ierr; 7838 7839 PetscFunctionBegin; 7840 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 7841 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 7842 if (dim != dE) PetscFunctionReturn(0); 7843 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7844 ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr); 7845 for (d = 0; d < dim; ++d) refVol *= 2.0; 7846 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7847 /* Make sure local coordinates are created, because that step is collective */ 7848 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 7849 for (c = cStart; c < cEnd; ++c) { 7850 DMPolytopeType ct; 7851 PetscInt unsplit; 7852 PetscBool ignoreZeroVol = PETSC_FALSE; 7853 7854 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 7855 switch (ct) { 7856 case DM_POLYTOPE_SEG_PRISM_TENSOR: 7857 case DM_POLYTOPE_TRI_PRISM_TENSOR: 7858 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 7859 ignoreZeroVol = PETSC_TRUE; break; 7860 default: break; 7861 } 7862 switch (ct) { 7863 case DM_POLYTOPE_TRI_PRISM: 7864 case DM_POLYTOPE_TRI_PRISM_TENSOR: 7865 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 7866 case DM_POLYTOPE_PYRAMID: 7867 continue; 7868 default: break; 7869 } 7870 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 7871 if (unsplit) continue; 7872 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 7873 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); 7874 ierr = PetscInfo2(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 7875 if (depth > 1 && !periodic) { 7876 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 7877 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); 7878 ierr = PetscInfo2(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 7879 } 7880 } 7881 PetscFunctionReturn(0); 7882 } 7883 7884 /*@ 7885 DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 7886 7887 Input Parameters: 7888 . dm - The DMPlex object 7889 7890 Notes: 7891 This is mainly intended for debugging/testing purposes. 7892 It currently checks only meshes with no partition overlapping. 7893 7894 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7895 7896 Level: developer 7897 7898 .seealso: DMGetPointSF(), DMSetFromOptions() 7899 @*/ 7900 PetscErrorCode DMPlexCheckPointSF(DM dm) 7901 { 7902 PetscSF pointSF; 7903 PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 7904 const PetscInt *locals, *rootdegree; 7905 PetscBool distributed; 7906 PetscErrorCode ierr; 7907 7908 PetscFunctionBegin; 7909 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7910 ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr); 7911 ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 7912 if (!distributed) PetscFunctionReturn(0); 7913 ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 7914 if (overlap) { 7915 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping"); 7916 PetscFunctionReturn(0); 7917 } 7918 if (!pointSF) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 7919 ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr); 7920 if (nroots < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 7921 ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 7922 ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 7923 7924 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 7925 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 7926 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 7927 for (l = 0; l < nleaves; ++l) { 7928 const PetscInt point = locals[l]; 7929 7930 if (point >= cStart && point < cEnd) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 7931 } 7932 7933 /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 7934 for (l = 0; l < nleaves; ++l) { 7935 const PetscInt point = locals[l]; 7936 const PetscInt *cone; 7937 PetscInt coneSize, c, idx; 7938 7939 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 7940 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 7941 for (c = 0; c < coneSize; ++c) { 7942 if (!rootdegree[cone[c]]) { 7943 ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr); 7944 if (idx < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 7945 } 7946 } 7947 } 7948 PetscFunctionReturn(0); 7949 } 7950 7951 typedef struct cell_stats 7952 { 7953 PetscReal min, max, sum, squaresum; 7954 PetscInt count; 7955 } cell_stats_t; 7956 7957 static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 7958 { 7959 PetscInt i, N = *len; 7960 7961 for (i = 0; i < N; i++) { 7962 cell_stats_t *A = (cell_stats_t *) a; 7963 cell_stats_t *B = (cell_stats_t *) b; 7964 7965 B->min = PetscMin(A->min,B->min); 7966 B->max = PetscMax(A->max,B->max); 7967 B->sum += A->sum; 7968 B->squaresum += A->squaresum; 7969 B->count += A->count; 7970 } 7971 } 7972 7973 /*@ 7974 DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 7975 7976 Collective on dm 7977 7978 Input Parameters: 7979 + dm - The DMPlex object 7980 . output - If true, statistics will be displayed on stdout 7981 - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 7982 7983 Notes: 7984 This is mainly intended for debugging/testing purposes. 7985 7986 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7987 7988 Level: developer 7989 7990 .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality() 7991 @*/ 7992 PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 7993 { 7994 DM dmCoarse; 7995 cell_stats_t stats, globalStats; 7996 MPI_Comm comm = PetscObjectComm((PetscObject)dm); 7997 PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 7998 PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 7999 PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 8000 PetscMPIInt rank,size; 8001 PetscErrorCode ierr; 8002 8003 PetscFunctionBegin; 8004 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8005 stats.min = PETSC_MAX_REAL; 8006 stats.max = PETSC_MIN_REAL; 8007 stats.sum = stats.squaresum = 0.; 8008 stats.count = 0; 8009 8010 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 8011 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8012 ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr); 8013 ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr); 8014 ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 8015 ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); 8016 for (c = cStart; c < cEnd; c++) { 8017 PetscInt i; 8018 PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8019 8020 ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 8021 if (detJ < 0.0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 8022 for (i = 0; i < PetscSqr(cdim); ++i) { 8023 frobJ += J[i] * J[i]; 8024 frobInvJ += invJ[i] * invJ[i]; 8025 } 8026 cond2 = frobJ * frobInvJ; 8027 cond = PetscSqrtReal(cond2); 8028 8029 stats.min = PetscMin(stats.min,cond); 8030 stats.max = PetscMax(stats.max,cond); 8031 stats.sum += cond; 8032 stats.squaresum += cond2; 8033 stats.count++; 8034 if (output && cond > limit) { 8035 PetscSection coordSection; 8036 Vec coordsLocal; 8037 PetscScalar *coords = NULL; 8038 PetscInt Nv, d, clSize, cl, *closure = NULL; 8039 8040 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8041 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8042 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8043 ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr); 8044 for (i = 0; i < Nv/cdim; ++i) { 8045 ierr = PetscSynchronizedPrintf(comm, " Vertex %D: (", i);CHKERRQ(ierr); 8046 for (d = 0; d < cdim; ++d) { 8047 if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);} 8048 ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr); 8049 } 8050 ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr); 8051 } 8052 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8053 for (cl = 0; cl < clSize*2; cl += 2) { 8054 const PetscInt edge = closure[cl]; 8055 8056 if ((edge >= eStart) && (edge < eEnd)) { 8057 PetscReal len; 8058 8059 ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr); 8060 ierr = PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr); 8061 } 8062 } 8063 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8064 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8065 } 8066 } 8067 if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 8068 8069 if (size > 1) { 8070 PetscMPIInt blockLengths[2] = {4,1}; 8071 MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8072 MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8073 MPI_Op statReduce; 8074 8075 ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRMPI(ierr); 8076 ierr = MPI_Type_commit(&statType);CHKERRMPI(ierr); 8077 ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRMPI(ierr); 8078 ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRMPI(ierr); 8079 ierr = MPI_Op_free(&statReduce);CHKERRMPI(ierr); 8080 ierr = MPI_Type_free(&statType);CHKERRMPI(ierr); 8081 } else { 8082 ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr); 8083 } 8084 if (!rank) { 8085 count = globalStats.count; 8086 min = globalStats.min; 8087 max = globalStats.max; 8088 mean = globalStats.sum / globalStats.count; 8089 stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8090 } 8091 8092 if (output) { 8093 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); 8094 } 8095 ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 8096 8097 ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 8098 if (dmCoarse) { 8099 PetscBool isplex; 8100 8101 ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 8102 if (isplex) { 8103 ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr); 8104 } 8105 } 8106 PetscFunctionReturn(0); 8107 } 8108 8109 /*@ 8110 DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8111 orthogonal quality below given tolerance. 8112 8113 Collective on dm 8114 8115 Input Parameters: 8116 + dm - The DMPlex object 8117 . fv - Optional PetscFV object for pre-computed cell/face centroid information 8118 - atol - [0, 1] Absolute tolerance for tagging cells. 8119 8120 Output Parameters: 8121 + OrthQual - Vec containing orthogonal quality per cell 8122 - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8123 8124 Options Database Keys: 8125 + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8126 supported. 8127 - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8128 8129 Notes: 8130 Orthogonal quality is given by the following formula: 8131 8132 \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8133 8134 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 8135 is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8136 current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8137 calculating the cosine of the angle between these vectors. 8138 8139 Orthogonal quality ranges from 1 (best) to 0 (worst). 8140 8141 This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8142 pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8143 8144 Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8145 8146 Level: intermediate 8147 8148 .seealso: DMPlexCheckCellShape(), DMCreateLabel() 8149 @*/ 8150 PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8151 { 8152 PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 8153 PetscInt *idx; 8154 PetscScalar *oqVals; 8155 const PetscScalar *cellGeomArr, *faceGeomArr; 8156 PetscReal *ci, *fi, *Ai; 8157 MPI_Comm comm; 8158 Vec cellgeom, facegeom; 8159 DM dmFace, dmCell; 8160 IS glob; 8161 ISLocalToGlobalMapping ltog; 8162 PetscViewer vwr; 8163 PetscErrorCode ierr; 8164 8165 PetscFunctionBegin; 8166 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8167 if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8168 PetscValidPointer(OrthQual, 4); 8169 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); 8170 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8171 ierr = DMGetDimension(dm, &nc);CHKERRQ(ierr); 8172 if (nc < 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc); 8173 { 8174 DMPlexInterpolatedFlag interpFlag; 8175 8176 ierr = DMPlexIsInterpolated(dm, &interpFlag);CHKERRQ(ierr); 8177 if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 8178 PetscMPIInt rank; 8179 8180 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8181 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 8182 } 8183 } 8184 if (OrthQualLabel) { 8185 PetscValidPointer(OrthQualLabel, 5); 8186 ierr = DMCreateLabel(dm, "Orthogonal_Quality");CHKERRQ(ierr); 8187 ierr = DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel);CHKERRQ(ierr); 8188 } else {*OrthQualLabel = NULL;} 8189 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8190 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8191 ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob);CHKERRQ(ierr); 8192 ierr = ISLocalToGlobalMappingCreateIS(glob, <og);CHKERRQ(ierr); 8193 ierr = ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 8194 ierr = VecCreate(comm, OrthQual);CHKERRQ(ierr); 8195 ierr = VecSetType(*OrthQual, VECSTANDARD);CHKERRQ(ierr); 8196 ierr = VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr); 8197 ierr = VecSetLocalToGlobalMapping(*OrthQual, ltog);CHKERRQ(ierr); 8198 ierr = VecSetUp(*OrthQual);CHKERRQ(ierr); 8199 ierr = ISDestroy(&glob);CHKERRQ(ierr); 8200 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 8201 ierr = DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL);CHKERRQ(ierr); 8202 ierr = VecGetArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8203 ierr = VecGetArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8204 ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr); 8205 ierr = VecGetDM(facegeom, &dmFace);CHKERRQ(ierr); 8206 ierr = PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai);CHKERRQ(ierr); 8207 for (cell = cStart; cell < cEnd; cellIter++,cell++) { 8208 PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 8209 PetscInt cellarr[2], *adj = NULL; 8210 PetscScalar *cArr, *fArr; 8211 PetscReal minvalc = 1.0, minvalf = 1.0; 8212 PetscFVCellGeom *cg; 8213 8214 idx[cellIter] = cell-cStart; 8215 cellarr[0] = cell; 8216 /* Make indexing into cellGeom easier */ 8217 ierr = DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg);CHKERRQ(ierr); 8218 ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj);CHKERRQ(ierr); 8219 /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 8220 ierr = PetscCalloc2(adjSize, &cArr, adjSize, &fArr);CHKERRQ(ierr); 8221 for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 8222 PetscInt i; 8223 const PetscInt neigh = adj[cellneigh]; 8224 PetscReal normci = 0, normfi = 0, normai = 0; 8225 PetscFVCellGeom *cgneigh; 8226 PetscFVFaceGeom *fg; 8227 8228 /* Don't count ourselves in the neighbor list */ 8229 if (neigh == cell) continue; 8230 ierr = DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh);CHKERRQ(ierr); 8231 cellarr[1] = neigh; 8232 { 8233 PetscInt numcovpts; 8234 const PetscInt *covpts; 8235 8236 ierr = DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 8237 ierr = DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg);CHKERRQ(ierr); 8238 ierr = DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 8239 } 8240 8241 /* Compute c_i, f_i and their norms */ 8242 for (i = 0; i < nc; i++) { 8243 ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 8244 fi[i] = fg->centroid[i] - cg->centroid[i]; 8245 Ai[i] = fg->normal[i]; 8246 normci += PetscPowReal(ci[i], 2); 8247 normfi += PetscPowReal(fi[i], 2); 8248 normai += PetscPowReal(Ai[i], 2); 8249 } 8250 normci = PetscSqrtReal(normci); 8251 normfi = PetscSqrtReal(normfi); 8252 normai = PetscSqrtReal(normai); 8253 8254 /* Normalize and compute for each face-cell-normal pair */ 8255 for (i = 0; i < nc; i++) { 8256 ci[i] = ci[i]/normci; 8257 fi[i] = fi[i]/normfi; 8258 Ai[i] = Ai[i]/normai; 8259 /* PetscAbs because I don't know if normals are guaranteed to point out */ 8260 cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 8261 fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 8262 } 8263 if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 8264 minvalc = PetscRealPart(cArr[cellneighiter]); 8265 } 8266 if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 8267 minvalf = PetscRealPart(fArr[cellneighiter]); 8268 } 8269 } 8270 ierr = PetscFree(adj);CHKERRQ(ierr); 8271 ierr = PetscFree2(cArr, fArr);CHKERRQ(ierr); 8272 /* Defer to cell if they're equal */ 8273 oqVals[cellIter] = PetscMin(minvalf, minvalc); 8274 if (OrthQualLabel) { 8275 if (PetscRealPart(oqVals[cellIter]) <= atol) {ierr = DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE);CHKERRQ(ierr);} 8276 } 8277 } 8278 ierr = VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES);CHKERRQ(ierr); 8279 ierr = VecAssemblyBegin(*OrthQual);CHKERRQ(ierr); 8280 ierr = VecAssemblyEnd(*OrthQual);CHKERRQ(ierr); 8281 ierr = VecRestoreArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8282 ierr = VecRestoreArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8283 ierr = PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL);CHKERRQ(ierr); 8284 if (OrthQualLabel) { 8285 if (vwr) {ierr = DMLabelView(*OrthQualLabel, vwr);CHKERRQ(ierr);} 8286 } 8287 ierr = PetscFree5(idx, oqVals, ci, fi, Ai);CHKERRQ(ierr); 8288 ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr); 8289 ierr = VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view");CHKERRQ(ierr); 8290 PetscFunctionReturn(0); 8291 } 8292 8293 /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 8294 * interpolator construction */ 8295 static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 8296 { 8297 PetscSection section, newSection, gsection; 8298 PetscSF sf; 8299 PetscBool hasConstraints, ghasConstraints; 8300 PetscErrorCode ierr; 8301 8302 PetscFunctionBegin; 8303 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8304 PetscValidPointer(odm,2); 8305 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 8306 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 8307 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 8308 if (!ghasConstraints) { 8309 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 8310 *odm = dm; 8311 PetscFunctionReturn(0); 8312 } 8313 ierr = DMClone(dm, odm);CHKERRQ(ierr); 8314 ierr = DMCopyFields(dm, *odm);CHKERRQ(ierr); 8315 ierr = DMGetLocalSection(*odm, &newSection);CHKERRQ(ierr); 8316 ierr = DMGetPointSF(*odm, &sf);CHKERRQ(ierr); 8317 ierr = PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 8318 ierr = DMSetGlobalSection(*odm, gsection);CHKERRQ(ierr); 8319 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 8320 PetscFunctionReturn(0); 8321 } 8322 8323 static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 8324 { 8325 DM dmco, dmfo; 8326 Mat interpo; 8327 Vec rscale; 8328 Vec cglobalo, clocal; 8329 Vec fglobal, fglobalo, flocal; 8330 PetscBool regular; 8331 PetscErrorCode ierr; 8332 8333 PetscFunctionBegin; 8334 ierr = DMGetFullDM(dmc, &dmco);CHKERRQ(ierr); 8335 ierr = DMGetFullDM(dmf, &dmfo);CHKERRQ(ierr); 8336 ierr = DMSetCoarseDM(dmfo, dmco);CHKERRQ(ierr); 8337 ierr = DMPlexGetRegularRefinement(dmf, ®ular);CHKERRQ(ierr); 8338 ierr = DMPlexSetRegularRefinement(dmfo, regular);CHKERRQ(ierr); 8339 ierr = DMCreateInterpolation(dmco, dmfo, &interpo, &rscale);CHKERRQ(ierr); 8340 ierr = DMCreateGlobalVector(dmco, &cglobalo);CHKERRQ(ierr); 8341 ierr = DMCreateLocalVector(dmc, &clocal);CHKERRQ(ierr); 8342 ierr = VecSet(cglobalo, 0.);CHKERRQ(ierr); 8343 ierr = VecSet(clocal, 0.);CHKERRQ(ierr); 8344 ierr = DMCreateGlobalVector(dmf, &fglobal);CHKERRQ(ierr); 8345 ierr = DMCreateGlobalVector(dmfo, &fglobalo);CHKERRQ(ierr); 8346 ierr = DMCreateLocalVector(dmf, &flocal);CHKERRQ(ierr); 8347 ierr = VecSet(fglobal, 0.);CHKERRQ(ierr); 8348 ierr = VecSet(fglobalo, 0.);CHKERRQ(ierr); 8349 ierr = VecSet(flocal, 0.);CHKERRQ(ierr); 8350 ierr = DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL);CHKERRQ(ierr); 8351 ierr = DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 8352 ierr = DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 8353 ierr = MatMult(interpo, cglobalo, fglobalo);CHKERRQ(ierr); 8354 ierr = DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 8355 ierr = DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 8356 ierr = DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 8357 ierr = DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 8358 *shift = fglobal; 8359 ierr = VecDestroy(&flocal);CHKERRQ(ierr); 8360 ierr = VecDestroy(&fglobalo);CHKERRQ(ierr); 8361 ierr = VecDestroy(&clocal);CHKERRQ(ierr); 8362 ierr = VecDestroy(&cglobalo);CHKERRQ(ierr); 8363 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 8364 ierr = MatDestroy(&interpo);CHKERRQ(ierr); 8365 ierr = DMDestroy(&dmfo);CHKERRQ(ierr); 8366 ierr = DMDestroy(&dmco);CHKERRQ(ierr); 8367 PetscFunctionReturn(0); 8368 } 8369 8370 PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 8371 { 8372 PetscObject shifto; 8373 Vec shift; 8374 8375 PetscErrorCode ierr; 8376 8377 PetscFunctionBegin; 8378 if (!interp) { 8379 Vec rscale; 8380 8381 ierr = DMCreateInterpolation(coarse, fine, &interp, &rscale);CHKERRQ(ierr); 8382 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 8383 } else { 8384 ierr = PetscObjectReference((PetscObject)interp);CHKERRQ(ierr); 8385 } 8386 ierr = PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto);CHKERRQ(ierr); 8387 if (!shifto) { 8388 ierr = DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift);CHKERRQ(ierr); 8389 ierr = PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift);CHKERRQ(ierr); 8390 shifto = (PetscObject) shift; 8391 ierr = VecDestroy(&shift);CHKERRQ(ierr); 8392 } 8393 shift = (Vec) shifto; 8394 ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr); 8395 ierr = VecAXPY(fineSol, 1.0, shift);CHKERRQ(ierr); 8396 ierr = MatDestroy(&interp);CHKERRQ(ierr); 8397 PetscFunctionReturn(0); 8398 } 8399 8400 /* Pointwise interpolation 8401 Just code FEM for now 8402 u^f = I u^c 8403 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 8404 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 8405 I_{ij} = psi^f_i phi^c_j 8406 */ 8407 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 8408 { 8409 PetscSection gsc, gsf; 8410 PetscInt m, n; 8411 void *ctx; 8412 DM cdm; 8413 PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 8414 PetscErrorCode ierr; 8415 8416 PetscFunctionBegin; 8417 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 8418 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 8419 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 8420 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 8421 8422 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 8423 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 8424 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 8425 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 8426 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 8427 8428 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 8429 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 8430 if (!isRefined || (regular && cdm == dmCoarse)) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx);CHKERRQ(ierr);} 8431 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 8432 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 8433 if (scaling) { 8434 /* Use naive scaling */ 8435 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 8436 } 8437 PetscFunctionReturn(0); 8438 } 8439 8440 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 8441 { 8442 PetscErrorCode ierr; 8443 VecScatter ctx; 8444 8445 PetscFunctionBegin; 8446 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 8447 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 8448 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 8449 PetscFunctionReturn(0); 8450 } 8451 8452 static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8453 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8454 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8455 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 8456 { 8457 g0[0] = 1.0; 8458 } 8459 8460 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 8461 { 8462 PetscSection gsc, gsf; 8463 PetscInt m, n; 8464 void *ctx; 8465 DM cdm; 8466 PetscBool regular; 8467 PetscErrorCode ierr; 8468 8469 PetscFunctionBegin; 8470 if (dmFine == dmCoarse) { 8471 DM dmc; 8472 PetscDS ds; 8473 Vec u; 8474 IS cellIS; 8475 PetscHashFormKey key; 8476 PetscInt depth; 8477 8478 ierr = DMClone(dmFine, &dmc);CHKERRQ(ierr); 8479 ierr = DMCopyDisc(dmFine, dmc);CHKERRQ(ierr); 8480 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 8481 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 8482 ierr = DMCreateMatrix(dmc, mass);CHKERRQ(ierr); 8483 ierr = DMGetGlobalVector(dmc, &u);CHKERRQ(ierr); 8484 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 8485 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 8486 ierr = MatZeroEntries(*mass);CHKERRQ(ierr); 8487 key.label = NULL; 8488 key.value = 0; 8489 key.field = 0; 8490 ierr = DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL);CHKERRQ(ierr); 8491 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 8492 ierr = DMRestoreGlobalVector(dmc, &u);CHKERRQ(ierr); 8493 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 8494 } else { 8495 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 8496 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 8497 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 8498 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 8499 8500 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 8501 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 8502 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 8503 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 8504 8505 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 8506 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 8507 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 8508 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 8509 } 8510 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 8511 PetscFunctionReturn(0); 8512 } 8513 8514 /*@ 8515 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 8516 8517 Input Parameter: 8518 . dm - The DMPlex object 8519 8520 Output Parameter: 8521 . regular - The flag 8522 8523 Level: intermediate 8524 8525 .seealso: DMPlexSetRegularRefinement() 8526 @*/ 8527 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 8528 { 8529 PetscFunctionBegin; 8530 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8531 PetscValidPointer(regular, 2); 8532 *regular = ((DM_Plex *) dm->data)->regularRefinement; 8533 PetscFunctionReturn(0); 8534 } 8535 8536 /*@ 8537 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 8538 8539 Input Parameters: 8540 + dm - The DMPlex object 8541 - regular - The flag 8542 8543 Level: intermediate 8544 8545 .seealso: DMPlexGetRegularRefinement() 8546 @*/ 8547 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 8548 { 8549 PetscFunctionBegin; 8550 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8551 ((DM_Plex *) dm->data)->regularRefinement = regular; 8552 PetscFunctionReturn(0); 8553 } 8554 8555 /*@ 8556 DMPlexGetCellRefinerType - Get the strategy for refining a cell 8557 8558 Input Parameter: 8559 . dm - The DMPlex object 8560 8561 Output Parameter: 8562 . cr - The strategy number 8563 8564 Level: intermediate 8565 8566 .seealso: DMPlexSetCellRefinerType(), DMPlexSetRegularRefinement() 8567 @*/ 8568 PetscErrorCode DMPlexGetCellRefinerType(DM dm, DMPlexCellRefinerType *cr) 8569 { 8570 PetscFunctionBegin; 8571 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8572 PetscValidPointer(cr, 2); 8573 *cr = ((DM_Plex *) dm->data)->cellRefiner; 8574 PetscFunctionReturn(0); 8575 } 8576 8577 /*@ 8578 DMPlexSetCellRefinerType - Set the strategy for refining a cell 8579 8580 Input Parameters: 8581 + dm - The DMPlex object 8582 - cr - The strategy number 8583 8584 Level: intermediate 8585 8586 .seealso: DMPlexGetCellRefinerType(), DMPlexGetRegularRefinement() 8587 @*/ 8588 PetscErrorCode DMPlexSetCellRefinerType(DM dm, DMPlexCellRefinerType cr) 8589 { 8590 PetscFunctionBegin; 8591 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8592 ((DM_Plex *) dm->data)->cellRefiner = cr; 8593 PetscFunctionReturn(0); 8594 } 8595 8596 /* anchors */ 8597 /*@ 8598 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 8599 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 8600 8601 not collective 8602 8603 Input Parameters: 8604 . dm - The DMPlex object 8605 8606 Output Parameters: 8607 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 8608 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 8609 8610 8611 Level: intermediate 8612 8613 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 8614 @*/ 8615 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 8616 { 8617 DM_Plex *plex = (DM_Plex *)dm->data; 8618 PetscErrorCode ierr; 8619 8620 PetscFunctionBegin; 8621 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8622 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 8623 if (anchorSection) *anchorSection = plex->anchorSection; 8624 if (anchorIS) *anchorIS = plex->anchorIS; 8625 PetscFunctionReturn(0); 8626 } 8627 8628 /*@ 8629 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 8630 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 8631 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 8632 8633 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 8634 DMGetConstraints() and filling in the entries in the constraint matrix. 8635 8636 collective on dm 8637 8638 Input Parameters: 8639 + dm - The DMPlex object 8640 . 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). 8641 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 8642 8643 The reference counts of anchorSection and anchorIS are incremented. 8644 8645 Level: intermediate 8646 8647 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 8648 @*/ 8649 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 8650 { 8651 DM_Plex *plex = (DM_Plex *)dm->data; 8652 PetscMPIInt result; 8653 PetscErrorCode ierr; 8654 8655 PetscFunctionBegin; 8656 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8657 if (anchorSection) { 8658 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 8659 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRMPI(ierr); 8660 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 8661 } 8662 if (anchorIS) { 8663 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 8664 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRMPI(ierr); 8665 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 8666 } 8667 8668 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 8669 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 8670 plex->anchorSection = anchorSection; 8671 8672 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 8673 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 8674 plex->anchorIS = anchorIS; 8675 8676 if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 8677 PetscInt size, a, pStart, pEnd; 8678 const PetscInt *anchors; 8679 8680 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 8681 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 8682 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 8683 for (a = 0; a < size; a++) { 8684 PetscInt p; 8685 8686 p = anchors[a]; 8687 if (p >= pStart && p < pEnd) { 8688 PetscInt dof; 8689 8690 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 8691 if (dof) { 8692 PetscErrorCode ierr2; 8693 8694 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 8695 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 8696 } 8697 } 8698 } 8699 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 8700 } 8701 /* reset the generic constraints */ 8702 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 8703 PetscFunctionReturn(0); 8704 } 8705 8706 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 8707 { 8708 PetscSection anchorSection; 8709 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 8710 PetscErrorCode ierr; 8711 8712 PetscFunctionBegin; 8713 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8714 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 8715 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 8716 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 8717 if (numFields) { 8718 PetscInt f; 8719 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 8720 8721 for (f = 0; f < numFields; f++) { 8722 PetscInt numComp; 8723 8724 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 8725 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 8726 } 8727 } 8728 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 8729 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 8730 pStart = PetscMax(pStart,sStart); 8731 pEnd = PetscMin(pEnd,sEnd); 8732 pEnd = PetscMax(pStart,pEnd); 8733 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 8734 for (p = pStart; p < pEnd; p++) { 8735 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 8736 if (dof) { 8737 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 8738 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 8739 for (f = 0; f < numFields; f++) { 8740 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 8741 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 8742 } 8743 } 8744 } 8745 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 8746 ierr = PetscObjectSetName((PetscObject) *cSec, "Constraint Section");CHKERRQ(ierr); 8747 PetscFunctionReturn(0); 8748 } 8749 8750 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 8751 { 8752 PetscSection aSec; 8753 PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 8754 const PetscInt *anchors; 8755 PetscInt numFields, f; 8756 IS aIS; 8757 PetscErrorCode ierr; 8758 MatType mtype; 8759 PetscBool iscuda,iskokkos; 8760 8761 PetscFunctionBegin; 8762 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8763 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 8764 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 8765 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 8766 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 8767 ierr = PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr); 8768 if (!iscuda) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr); } 8769 ierr = PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos);CHKERRQ(ierr); 8770 if (!iskokkos) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos);CHKERRQ(ierr); } 8771 if (iscuda) mtype = MATSEQAIJCUSPARSE; 8772 else if (iskokkos) mtype = MATSEQAIJKOKKOS; 8773 else mtype = MATSEQAIJ; 8774 ierr = MatSetType(*cMat,mtype);CHKERRQ(ierr); 8775 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 8776 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 8777 /* cSec will be a subset of aSec and section */ 8778 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 8779 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 8780 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 8781 i[0] = 0; 8782 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 8783 for (p = pStart; p < pEnd; p++) { 8784 PetscInt rDof, rOff, r; 8785 8786 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 8787 if (!rDof) continue; 8788 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 8789 if (numFields) { 8790 for (f = 0; f < numFields; f++) { 8791 annz = 0; 8792 for (r = 0; r < rDof; r++) { 8793 a = anchors[rOff + r]; 8794 if (a < sStart || a >= sEnd) continue; 8795 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 8796 annz += aDof; 8797 } 8798 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 8799 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 8800 for (q = 0; q < dof; q++) { 8801 i[off + q + 1] = i[off + q] + annz; 8802 } 8803 } 8804 } 8805 else { 8806 annz = 0; 8807 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 8808 for (q = 0; q < dof; q++) { 8809 a = anchors[rOff + q]; 8810 if (a < sStart || a >= sEnd) continue; 8811 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 8812 annz += aDof; 8813 } 8814 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 8815 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 8816 for (q = 0; q < dof; q++) { 8817 i[off + q + 1] = i[off + q] + annz; 8818 } 8819 } 8820 } 8821 nnz = i[m]; 8822 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 8823 offset = 0; 8824 for (p = pStart; p < pEnd; p++) { 8825 if (numFields) { 8826 for (f = 0; f < numFields; f++) { 8827 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 8828 for (q = 0; q < dof; q++) { 8829 PetscInt rDof, rOff, r; 8830 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 8831 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 8832 for (r = 0; r < rDof; r++) { 8833 PetscInt s; 8834 8835 a = anchors[rOff + r]; 8836 if (a < sStart || a >= sEnd) continue; 8837 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 8838 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 8839 for (s = 0; s < aDof; s++) { 8840 j[offset++] = aOff + s; 8841 } 8842 } 8843 } 8844 } 8845 } 8846 else { 8847 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 8848 for (q = 0; q < dof; q++) { 8849 PetscInt rDof, rOff, r; 8850 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 8851 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 8852 for (r = 0; r < rDof; r++) { 8853 PetscInt s; 8854 8855 a = anchors[rOff + r]; 8856 if (a < sStart || a >= sEnd) continue; 8857 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 8858 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 8859 for (s = 0; s < aDof; s++) { 8860 j[offset++] = aOff + s; 8861 } 8862 } 8863 } 8864 } 8865 } 8866 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 8867 ierr = PetscFree(i);CHKERRQ(ierr); 8868 ierr = PetscFree(j);CHKERRQ(ierr); 8869 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 8870 PetscFunctionReturn(0); 8871 } 8872 8873 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 8874 { 8875 DM_Plex *plex = (DM_Plex *)dm->data; 8876 PetscSection anchorSection, section, cSec; 8877 Mat cMat; 8878 PetscErrorCode ierr; 8879 8880 PetscFunctionBegin; 8881 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8882 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 8883 if (anchorSection) { 8884 PetscInt Nf; 8885 8886 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 8887 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 8888 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 8889 ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 8890 if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 8891 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 8892 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 8893 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 8894 } 8895 PetscFunctionReturn(0); 8896 } 8897 8898 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 8899 { 8900 IS subis; 8901 PetscSection section, subsection; 8902 PetscErrorCode ierr; 8903 8904 PetscFunctionBegin; 8905 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 8906 if (!section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 8907 if (!subdm) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 8908 /* Create subdomain */ 8909 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 8910 /* Create submodel */ 8911 ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr); 8912 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 8913 ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr); 8914 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 8915 ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 8916 /* Create map from submodel to global model */ 8917 if (is) { 8918 PetscSection sectionGlobal, subsectionGlobal; 8919 IS spIS; 8920 const PetscInt *spmap; 8921 PetscInt *subIndices; 8922 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 8923 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 8924 8925 ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 8926 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 8927 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 8928 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 8929 ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 8930 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 8931 for (p = pStart; p < pEnd; ++p) { 8932 PetscInt gdof, pSubSize = 0; 8933 8934 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 8935 if (gdof > 0) { 8936 for (f = 0; f < Nf; ++f) { 8937 PetscInt fdof, fcdof; 8938 8939 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 8940 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 8941 pSubSize += fdof-fcdof; 8942 } 8943 subSize += pSubSize; 8944 if (pSubSize) { 8945 if (bs < 0) { 8946 bs = pSubSize; 8947 } else if (bs != pSubSize) { 8948 /* Layout does not admit a pointwise block size */ 8949 bs = 1; 8950 } 8951 } 8952 } 8953 } 8954 /* Must have same blocksize on all procs (some might have no points) */ 8955 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 8956 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 8957 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 8958 else {bs = bsMinMax[0];} 8959 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 8960 for (p = pStart; p < pEnd; ++p) { 8961 PetscInt gdof, goff; 8962 8963 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 8964 if (gdof > 0) { 8965 const PetscInt point = spmap[p]; 8966 8967 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 8968 for (f = 0; f < Nf; ++f) { 8969 PetscInt fdof, fcdof, fc, f2, poff = 0; 8970 8971 /* Can get rid of this loop by storing field information in the global section */ 8972 for (f2 = 0; f2 < f; ++f2) { 8973 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 8974 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 8975 poff += fdof-fcdof; 8976 } 8977 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8978 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 8979 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 8980 subIndices[subOff] = goff+poff+fc; 8981 } 8982 } 8983 } 8984 } 8985 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 8986 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 8987 if (bs > 1) { 8988 /* We need to check that the block size does not come from non-contiguous fields */ 8989 PetscInt i, j, set = 1; 8990 for (i = 0; i < subSize; i += bs) { 8991 for (j = 0; j < bs; ++j) { 8992 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 8993 } 8994 } 8995 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 8996 } 8997 /* Attach nullspace */ 8998 for (f = 0; f < Nf; ++f) { 8999 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9000 if ((*subdm)->nullspaceConstructors[f]) break; 9001 } 9002 if (f < Nf) { 9003 MatNullSpace nullSpace; 9004 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace);CHKERRQ(ierr); 9005 9006 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 9007 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 9008 } 9009 } 9010 PetscFunctionReturn(0); 9011 } 9012 9013 /*@ 9014 DMPlexMonitorThroughput - Report the cell throughput of FE integration 9015 9016 Input Parameter: 9017 - dm - The DM 9018 9019 Level: developer 9020 9021 Options Database Keys: 9022 . -dm_plex_monitor_throughput - Activate the monitor 9023 9024 .seealso: DMSetFromOptions(), DMPlexCreate() 9025 @*/ 9026 PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9027 { 9028 #if defined(PETSC_USE_LOG) 9029 PetscStageLog stageLog; 9030 PetscLogEvent event; 9031 PetscLogStage stage; 9032 PetscEventPerfInfo eventInfo; 9033 PetscReal cellRate, flopRate; 9034 PetscInt cStart, cEnd, Nf, N; 9035 const char *name; 9036 PetscErrorCode ierr; 9037 #endif 9038 9039 PetscFunctionBegin; 9040 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9041 #if defined(PETSC_USE_LOG) 9042 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 9043 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9044 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9045 ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 9046 ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr); 9047 ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr); 9048 ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr); 9049 N = (cEnd - cStart)*Nf*eventInfo.count; 9050 flopRate = eventInfo.flops/eventInfo.time; 9051 cellRate = N/eventInfo.time; 9052 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); 9053 #else 9054 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9055 #endif 9056 PetscFunctionReturn(0); 9057 } 9058