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 case 12: /* Localized triangle */ 258 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); 259 break; 260 case 8: 261 case 16: /* Localized quadrilateral */ 262 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); 263 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); 264 break; 265 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords); 266 } 267 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 268 } 269 ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr); 270 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 271 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 272 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 273 } 274 if (Nf > 1) { 275 ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr); 276 ierr = ISDestroy(&fis);CHKERRQ(ierr); 277 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 278 } 279 } 280 PetscFunctionReturn(0); 281 } 282 283 static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 284 { 285 DM dm; 286 Vec locv; 287 const char *name; 288 PetscSection section; 289 PetscInt pStart, pEnd; 290 PetscInt numFields; 291 PetscViewerVTKFieldType ft; 292 PetscErrorCode ierr; 293 294 PetscFunctionBegin; 295 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 296 ierr = DMCreateLocalVector(dm, &locv);CHKERRQ(ierr); /* VTK viewer requires exclusive ownership of the vector */ 297 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 298 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 299 ierr = VecCopy(v, locv);CHKERRQ(ierr); 300 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 301 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 302 if (!numFields) { 303 ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 304 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 305 } else { 306 PetscInt f; 307 308 for (f = 0; f < numFields; f++) { 309 ierr = DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft);CHKERRQ(ierr); 310 if (ft == PETSC_VTK_INVALID) continue; 311 ierr = PetscObjectReference((PetscObject)locv);CHKERRQ(ierr); 312 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 313 } 314 ierr = VecDestroy(&locv);CHKERRQ(ierr); 315 } 316 PetscFunctionReturn(0); 317 } 318 319 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 320 { 321 DM dm; 322 PetscBool isvtk, ishdf5, isdraw, isglvis; 323 PetscErrorCode ierr; 324 325 PetscFunctionBegin; 326 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 327 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 328 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 329 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 330 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 331 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 332 if (isvtk || ishdf5 || isdraw || isglvis) { 333 PetscInt i,numFields; 334 PetscObject fe; 335 PetscBool fem = PETSC_FALSE; 336 Vec locv = v; 337 const char *name; 338 PetscInt step; 339 PetscReal time; 340 341 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 342 for (i=0; i<numFields; i++) { 343 ierr = DMGetField(dm, i, NULL, &fe);CHKERRQ(ierr); 344 if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; } 345 } 346 if (fem) { 347 PetscObject isZero; 348 349 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 350 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 351 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 352 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 353 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 354 ierr = VecCopy(v, locv);CHKERRQ(ierr); 355 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 356 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr); 357 } 358 if (isvtk) { 359 ierr = VecView_Plex_Local_VTK(locv, viewer);CHKERRQ(ierr); 360 } else if (ishdf5) { 361 #if defined(PETSC_HAVE_HDF5) 362 ierr = VecView_Plex_Local_HDF5_Internal(locv, viewer);CHKERRQ(ierr); 363 #else 364 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 365 #endif 366 } else if (isdraw) { 367 ierr = VecView_Plex_Local_Draw(locv, viewer);CHKERRQ(ierr); 368 } else if (isglvis) { 369 ierr = DMGetOutputSequenceNumber(dm, &step, NULL);CHKERRQ(ierr); 370 ierr = PetscViewerGLVisSetSnapId(viewer, step);CHKERRQ(ierr); 371 ierr = VecView_GLVis(locv, viewer);CHKERRQ(ierr); 372 } 373 if (fem) { 374 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 375 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 376 } 377 } else { 378 PetscBool isseq; 379 380 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 381 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 382 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 383 } 384 PetscFunctionReturn(0); 385 } 386 387 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 388 { 389 DM dm; 390 PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii; 391 PetscErrorCode ierr; 392 393 PetscFunctionBegin; 394 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 395 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 396 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 397 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 398 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 399 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 400 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 401 if (isvtk || isdraw || isglvis) { 402 Vec locv; 403 PetscObject isZero; 404 const char *name; 405 406 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 407 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 408 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 409 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 410 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 411 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 412 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 413 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 414 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 415 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 416 } else if (ishdf5) { 417 #if defined(PETSC_HAVE_HDF5) 418 ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 419 #else 420 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 421 #endif 422 } else if (isexodusii) { 423 #if defined(PETSC_HAVE_EXODUSII) 424 ierr = VecView_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 425 #else 426 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 427 #endif 428 } else { 429 PetscBool isseq; 430 431 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 432 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 433 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 434 } 435 PetscFunctionReturn(0); 436 } 437 438 PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 439 { 440 DM dm; 441 MPI_Comm comm; 442 PetscViewerFormat format; 443 Vec v; 444 PetscBool isvtk, ishdf5; 445 PetscErrorCode ierr; 446 447 PetscFunctionBegin; 448 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 449 ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 450 if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 451 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 452 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 453 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 454 if (format == PETSC_VIEWER_NATIVE) { 455 /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 456 /* this need a better fix */ 457 if (dm->useNatural) { 458 if (dm->sfNatural) { 459 const char *vecname; 460 PetscInt n, nroots; 461 462 ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr); 463 ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 464 if (n == nroots) { 465 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 466 ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 467 ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 468 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 469 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 470 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 471 } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 472 } else v = originalv; 473 } else v = originalv; 474 475 if (ishdf5) { 476 #if defined(PETSC_HAVE_HDF5) 477 ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 478 #else 479 SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 480 #endif 481 } else if (isvtk) { 482 SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 483 } else { 484 PetscBool isseq; 485 486 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 487 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 488 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 489 } 490 if (v != originalv) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 491 PetscFunctionReturn(0); 492 } 493 494 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 495 { 496 DM dm; 497 PetscBool ishdf5; 498 PetscErrorCode ierr; 499 500 PetscFunctionBegin; 501 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 502 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 503 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 504 if (ishdf5) { 505 DM dmBC; 506 Vec gv; 507 const char *name; 508 509 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 510 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 511 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 512 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 513 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 514 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 515 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 516 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 517 } else { 518 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 519 } 520 PetscFunctionReturn(0); 521 } 522 523 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 524 { 525 DM dm; 526 PetscBool ishdf5,isexodusii; 527 PetscErrorCode ierr; 528 529 PetscFunctionBegin; 530 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 531 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 532 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 533 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 534 if (ishdf5) { 535 #if defined(PETSC_HAVE_HDF5) 536 ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 537 #else 538 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 539 #endif 540 } else if (isexodusii) { 541 #if defined(PETSC_HAVE_EXODUSII) 542 ierr = VecLoad_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 543 #else 544 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 545 #endif 546 } else { 547 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 548 } 549 PetscFunctionReturn(0); 550 } 551 552 PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 553 { 554 DM dm; 555 PetscViewerFormat format; 556 PetscBool ishdf5; 557 PetscErrorCode ierr; 558 559 PetscFunctionBegin; 560 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 561 if (!dm) SETERRQ(PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 562 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 563 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 564 if (format == PETSC_VIEWER_NATIVE) { 565 if (dm->useNatural) { 566 if (dm->sfNatural) { 567 if (ishdf5) { 568 #if defined(PETSC_HAVE_HDF5) 569 Vec v; 570 const char *vecname; 571 572 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 573 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 574 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 575 ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 576 ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 577 ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 578 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 579 #else 580 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 581 #endif 582 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 583 } 584 } else { 585 ierr = VecLoad_Default(originalv, viewer);CHKERRQ(ierr); 586 } 587 } 588 PetscFunctionReturn(0); 589 } 590 591 PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 592 { 593 PetscSection coordSection; 594 Vec coordinates; 595 DMLabel depthLabel, celltypeLabel; 596 const char *name[4]; 597 const PetscScalar *a; 598 PetscInt dim, pStart, pEnd, cStart, cEnd, c; 599 PetscErrorCode ierr; 600 601 PetscFunctionBegin; 602 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 603 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 604 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 605 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 606 ierr = DMPlexGetCellTypeLabel(dm, &celltypeLabel);CHKERRQ(ierr); 607 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 608 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 609 ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 610 name[0] = "vertex"; 611 name[1] = "edge"; 612 name[dim-1] = "face"; 613 name[dim] = "cell"; 614 for (c = cStart; c < cEnd; ++c) { 615 PetscInt *closure = NULL; 616 PetscInt closureSize, cl, ct; 617 618 ierr = DMLabelGetValue(celltypeLabel, c, &ct);CHKERRQ(ierr); 619 ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]);CHKERRQ(ierr); 620 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 621 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 622 for (cl = 0; cl < closureSize*2; cl += 2) { 623 PetscInt point = closure[cl], depth, dof, off, d, p; 624 625 if ((point < pStart) || (point >= pEnd)) continue; 626 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 627 if (!dof) continue; 628 ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 629 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 630 ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr); 631 for (p = 0; p < dof/dim; ++p) { 632 ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 633 for (d = 0; d < dim; ++d) { 634 if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 635 ierr = PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 636 } 637 ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 638 } 639 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 640 } 641 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 642 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 643 } 644 ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 645 PetscFunctionReturn(0); 646 } 647 648 static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 649 { 650 DM_Plex *mesh = (DM_Plex*) dm->data; 651 DM cdm; 652 PetscSection coordSection; 653 Vec coordinates; 654 PetscViewerFormat format; 655 PetscErrorCode ierr; 656 657 PetscFunctionBegin; 658 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 659 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 660 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 661 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 662 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 663 const char *name; 664 PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 665 PetscInt pStart, pEnd, p, numLabels, l; 666 PetscMPIInt rank, size; 667 668 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 669 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 670 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 671 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 672 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 673 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 674 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 675 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 676 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 677 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 678 ierr = PetscViewerASCIIPrintf(viewer, "Supports:\n", name);CHKERRQ(ierr); 679 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 680 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize);CHKERRQ(ierr); 681 for (p = pStart; p < pEnd; ++p) { 682 PetscInt dof, off, s; 683 684 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 685 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 686 for (s = off; s < off+dof; ++s) { 687 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 688 } 689 } 690 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 691 ierr = PetscViewerASCIIPrintf(viewer, "Cones:\n", name);CHKERRQ(ierr); 692 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize);CHKERRQ(ierr); 693 for (p = pStart; p < pEnd; ++p) { 694 PetscInt dof, off, c; 695 696 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 697 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 698 for (c = off; c < off+dof; ++c) { 699 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 700 } 701 } 702 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 703 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 704 if (coordSection && coordinates) { 705 ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr); 706 } 707 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 708 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 709 for (l = 0; l < numLabels; ++l) { 710 DMLabel label; 711 PetscBool isdepth; 712 const char *name; 713 714 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 715 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 716 if (isdepth) continue; 717 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 718 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 719 } 720 if (size > 1) { 721 PetscSF sf; 722 723 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 724 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 725 } 726 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 727 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 728 const char *name, *color; 729 const char *defcolors[3] = {"gray", "orange", "green"}; 730 const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 731 char lname[PETSC_MAX_PATH_LEN]; 732 PetscReal scale = 2.0; 733 PetscReal tikzscale = 1.0; 734 PetscBool useNumbers = PETSC_TRUE, useLabels, useColors; 735 double tcoords[3]; 736 PetscScalar *coords; 737 PetscInt numLabels, l, numColors, numLColors, dim, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 738 PetscMPIInt rank, size; 739 char **names, **colors, **lcolors; 740 PetscBool plotEdges, flg, lflg; 741 PetscBT wp = NULL; 742 PetscInt pEnd, pStart; 743 744 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 745 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 746 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 747 numLabels = PetscMax(numLabels, 10); 748 numColors = 10; 749 numLColors = 10; 750 ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 751 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 752 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL);CHKERRQ(ierr); 753 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 754 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 755 if (!useLabels) numLabels = 0; 756 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 757 if (!useColors) { 758 numColors = 3; 759 for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 760 } 761 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 762 if (!useColors) { 763 numLColors = 4; 764 for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 765 } 766 ierr = PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg);CHKERRQ(ierr); 767 plotEdges = (PetscBool)(depth > 1 && useNumbers && dim < 3); 768 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg);CHKERRQ(ierr); 769 if (flg && plotEdges && depth < dim) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 770 if (depth < dim) plotEdges = PETSC_FALSE; 771 772 /* filter points with labelvalue != labeldefaultvalue */ 773 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 774 if (lflg) { 775 DMLabel lbl; 776 777 ierr = DMGetLabel(dm, lname, &lbl);CHKERRQ(ierr); 778 if (lbl) { 779 PetscInt val, defval; 780 781 ierr = DMLabelGetDefaultValue(lbl, &defval);CHKERRQ(ierr); 782 ierr = PetscBTCreate(pEnd-pStart, &wp);CHKERRQ(ierr); 783 for (c = pStart; c < pEnd; c++) { 784 PetscInt *closure = NULL; 785 PetscInt closureSize; 786 787 ierr = DMLabelGetValue(lbl, c, &val);CHKERRQ(ierr); 788 if (val == defval) continue; 789 790 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 791 for (p = 0; p < closureSize*2; p += 2) { 792 ierr = PetscBTSet(wp, closure[p] - pStart);CHKERRQ(ierr); 793 } 794 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 795 } 796 } 797 } 798 799 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 800 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 801 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 802 ierr = PetscViewerASCIIPrintf(viewer, "\ 803 \\documentclass[tikz]{standalone}\n\n\ 804 \\usepackage{pgflibraryshapes}\n\ 805 \\usetikzlibrary{backgrounds}\n\ 806 \\usetikzlibrary{arrows}\n\ 807 \\begin{document}\n");CHKERRQ(ierr); 808 if (size > 1) { 809 ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 810 for (p = 0; p < size; ++p) { 811 if (p > 0 && p == size-1) { 812 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 813 } else if (p > 0) { 814 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 815 } 816 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 817 } 818 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 819 } 820 ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale);CHKERRQ(ierr); 821 822 /* Plot vertices */ 823 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 824 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 825 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 826 for (v = vStart; v < vEnd; ++v) { 827 PetscInt off, dof, d; 828 PetscBool isLabeled = PETSC_FALSE; 829 830 if (wp && !PetscBTLookup(wp,v - pStart)) continue; 831 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 832 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 833 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 834 if (PetscUnlikely(dof > 3)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 835 for (d = 0; d < dof; ++d) { 836 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 837 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 838 } 839 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 840 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 841 for (d = 0; d < dof; ++d) { 842 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 843 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]);CHKERRQ(ierr); 844 } 845 color = colors[rank%numColors]; 846 for (l = 0; l < numLabels; ++l) { 847 PetscInt val; 848 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 849 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 850 } 851 if (useNumbers) { 852 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 853 } else { 854 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 855 } 856 } 857 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 858 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 859 /* Plot cells */ 860 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 861 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 862 if (dim == 3 || !useNumbers) { 863 for (e = eStart; e < eEnd; ++e) { 864 const PetscInt *cone; 865 866 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 867 color = colors[rank%numColors]; 868 for (l = 0; l < numLabels; ++l) { 869 PetscInt val; 870 ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 871 if (val >= 0) {color = lcolors[l%numLColors]; break;} 872 } 873 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 874 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 875 } 876 } else { 877 for (c = cStart; c < cEnd; ++c) { 878 PetscInt *closure = NULL; 879 PetscInt closureSize, firstPoint = -1; 880 881 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 882 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 883 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 884 for (p = 0; p < closureSize*2; p += 2) { 885 const PetscInt point = closure[p]; 886 887 if ((point < vStart) || (point >= vEnd)) continue; 888 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 889 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", point, rank);CHKERRQ(ierr); 890 if (firstPoint < 0) firstPoint = point; 891 } 892 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 893 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d);\n", firstPoint, rank);CHKERRQ(ierr); 894 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 895 } 896 } 897 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 898 for (c = cStart; c < cEnd; ++c) { 899 double ccoords[3] = {0.0, 0.0, 0.0}; 900 PetscBool isLabeled = PETSC_FALSE; 901 PetscInt *closure = NULL; 902 PetscInt closureSize, dof, d, n = 0; 903 904 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 905 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 906 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 907 for (p = 0; p < closureSize*2; p += 2) { 908 const PetscInt point = closure[p]; 909 PetscInt off; 910 911 if ((point < vStart) || (point >= vEnd)) continue; 912 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 913 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 914 for (d = 0; d < dof; ++d) { 915 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 916 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 917 } 918 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 919 if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 920 for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 921 ++n; 922 } 923 for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 924 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 925 for (d = 0; d < dof; ++d) { 926 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 927 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]);CHKERRQ(ierr); 928 } 929 color = colors[rank%numColors]; 930 for (l = 0; l < numLabels; ++l) { 931 PetscInt val; 932 ierr = DMGetLabelValue(dm, names[l], c, &val);CHKERRQ(ierr); 933 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 934 } 935 if (useNumbers) { 936 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c);CHKERRQ(ierr); 937 } else { 938 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 939 } 940 } 941 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 942 /* Plot edges */ 943 if (plotEdges) { 944 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 945 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 946 for (e = eStart; e < eEnd; ++e) { 947 const PetscInt *cone; 948 PetscInt coneSize, offA, offB, dof, d; 949 950 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 951 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 952 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 953 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 954 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 955 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 956 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 957 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 958 for (d = 0; d < dof; ++d) { 959 tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 960 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 961 } 962 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 963 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 964 for (d = 0; d < dof; ++d) { 965 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 966 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr); 967 } 968 color = colors[rank%numColors]; 969 for (l = 0; l < numLabels; ++l) { 970 PetscInt val; 971 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 972 if (val >= 0) {color = lcolors[l%numLColors]; break;} 973 } 974 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 975 } 976 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 977 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 978 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 979 } 980 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 981 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 982 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 983 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 984 for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 985 for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 986 for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 987 ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 988 ierr = PetscBTDestroy(&wp);CHKERRQ(ierr); 989 } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 990 Vec cown,acown; 991 VecScatter sct; 992 ISLocalToGlobalMapping g2l; 993 IS gid,acis; 994 MPI_Comm comm,ncomm = MPI_COMM_NULL; 995 MPI_Group ggroup,ngroup; 996 PetscScalar *array,nid; 997 const PetscInt *idxs; 998 PetscInt *idxs2,*start,*adjacency,*work; 999 PetscInt64 lm[3],gm[3]; 1000 PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 1001 PetscMPIInt d1,d2,rank; 1002 1003 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1004 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 1005 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1006 ierr = MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm);CHKERRMPI(ierr); 1007 #endif 1008 if (ncomm != MPI_COMM_NULL) { 1009 ierr = MPI_Comm_group(comm,&ggroup);CHKERRMPI(ierr); 1010 ierr = MPI_Comm_group(ncomm,&ngroup);CHKERRMPI(ierr); 1011 d1 = 0; 1012 ierr = MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2);CHKERRMPI(ierr); 1013 nid = d2; 1014 ierr = MPI_Group_free(&ggroup);CHKERRMPI(ierr); 1015 ierr = MPI_Group_free(&ngroup);CHKERRMPI(ierr); 1016 ierr = MPI_Comm_free(&ncomm);CHKERRMPI(ierr); 1017 } else nid = 0.0; 1018 1019 /* Get connectivity */ 1020 ierr = DMPlexGetVTKCellHeight(dm,&cellHeight);CHKERRQ(ierr); 1021 ierr = DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid);CHKERRQ(ierr); 1022 1023 /* filter overlapped local cells */ 1024 ierr = DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd);CHKERRQ(ierr); 1025 ierr = ISGetIndices(gid,&idxs);CHKERRQ(ierr); 1026 ierr = ISGetLocalSize(gid,&cum);CHKERRQ(ierr); 1027 ierr = PetscMalloc1(cum,&idxs2);CHKERRQ(ierr); 1028 for (c = cStart, cum = 0; c < cEnd; c++) { 1029 if (idxs[c-cStart] < 0) continue; 1030 idxs2[cum++] = idxs[c-cStart]; 1031 } 1032 ierr = ISRestoreIndices(gid,&idxs);CHKERRQ(ierr); 1033 if (numVertices != cum) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum); 1034 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1035 ierr = ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid);CHKERRQ(ierr); 1036 1037 /* support for node-aware cell locality */ 1038 ierr = ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis);CHKERRQ(ierr); 1039 ierr = VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown);CHKERRQ(ierr); 1040 ierr = VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown);CHKERRQ(ierr); 1041 ierr = VecGetArray(cown,&array);CHKERRQ(ierr); 1042 for (c = 0; c < numVertices; c++) array[c] = nid; 1043 ierr = VecRestoreArray(cown,&array);CHKERRQ(ierr); 1044 ierr = VecScatterCreate(cown,acis,acown,NULL,&sct);CHKERRQ(ierr); 1045 ierr = VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1046 ierr = VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1047 ierr = ISDestroy(&acis);CHKERRQ(ierr); 1048 ierr = VecScatterDestroy(&sct);CHKERRQ(ierr); 1049 ierr = VecDestroy(&cown);CHKERRQ(ierr); 1050 1051 /* compute edgeCut */ 1052 for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 1053 ierr = PetscMalloc1(cum,&work);CHKERRQ(ierr); 1054 ierr = ISLocalToGlobalMappingCreateIS(gid,&g2l);CHKERRQ(ierr); 1055 ierr = ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 1056 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1057 ierr = VecGetArray(acown,&array);CHKERRQ(ierr); 1058 for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 1059 PetscInt totl; 1060 1061 totl = start[c+1]-start[c]; 1062 ierr = ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work);CHKERRQ(ierr); 1063 for (i = 0; i < totl; i++) { 1064 if (work[i] < 0) { 1065 ect += 1; 1066 ectn += (array[i + start[c]] != nid) ? 0 : 1; 1067 } 1068 } 1069 } 1070 ierr = PetscFree(work);CHKERRQ(ierr); 1071 ierr = VecRestoreArray(acown,&array);CHKERRQ(ierr); 1072 lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 1073 lm[1] = -numVertices; 1074 ierr = MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm);CHKERRMPI(ierr); 1075 ierr = PetscViewerASCIIPrintf(viewer," Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]);CHKERRQ(ierr); 1076 lm[0] = ect; /* edgeCut */ 1077 lm[1] = ectn; /* node-aware edgeCut */ 1078 lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 1079 ierr = MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr); 1080 ierr = PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]);CHKERRQ(ierr); 1081 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1082 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); 1083 #else 1084 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0);CHKERRQ(ierr); 1085 #endif 1086 ierr = ISLocalToGlobalMappingDestroy(&g2l);CHKERRQ(ierr); 1087 ierr = PetscFree(start);CHKERRQ(ierr); 1088 ierr = PetscFree(adjacency);CHKERRQ(ierr); 1089 ierr = VecDestroy(&acown);CHKERRQ(ierr); 1090 } else { 1091 const char *name; 1092 PetscInt *sizes, *hybsizes, *ghostsizes; 1093 PetscInt locDepth, depth, cellHeight, dim, d; 1094 PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1095 PetscInt numLabels, l; 1096 DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1097 MPI_Comm comm; 1098 PetscMPIInt size, rank; 1099 1100 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1101 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1102 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1103 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1104 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 1105 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 1106 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1107 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1108 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 1109 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 1110 ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRMPI(ierr); 1111 ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr); 1112 gcNum = gcEnd - gcStart; 1113 ierr = PetscCalloc3(size,&sizes,size,&hybsizes,size,&ghostsizes);CHKERRQ(ierr); 1114 for (d = 0; d <= depth; d++) { 1115 PetscInt Nc[2] = {0, 0}, ict; 1116 1117 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 1118 if (pStart < pEnd) {ierr = DMPlexGetCellType(dm, pStart, &ct0);CHKERRQ(ierr);} 1119 ict = ct0; 1120 ierr = MPI_Bcast(&ict, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1121 ct0 = (DMPolytopeType) ict; 1122 for (p = pStart; p < pEnd; ++p) { 1123 DMPolytopeType ct; 1124 1125 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 1126 if (ct == ct0) ++Nc[0]; 1127 else ++Nc[1]; 1128 } 1129 ierr = MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1130 ierr = MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1131 if (d == depth) {ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);} 1132 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", (depth == 1) && d ? dim : d);CHKERRQ(ierr); 1133 for (p = 0; p < size; ++p) { 1134 if (!rank) { 1135 ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]);CHKERRQ(ierr); 1136 if (hybsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]);CHKERRQ(ierr);} 1137 if (ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);} 1138 } 1139 } 1140 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 1141 } 1142 ierr = PetscFree3(sizes,hybsizes,ghostsizes);CHKERRQ(ierr); 1143 { 1144 const PetscReal *maxCell; 1145 const PetscReal *L; 1146 const DMBoundaryType *bd; 1147 PetscBool per, localized; 1148 1149 ierr = DMGetPeriodicity(dm, &per, &maxCell, &L, &bd);CHKERRQ(ierr); 1150 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 1151 if (per) { 1152 ierr = PetscViewerASCIIPrintf(viewer, "Periodic mesh (");CHKERRQ(ierr); 1153 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1154 for (d = 0; d < dim; ++d) { 1155 if (bd && d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1156 if (bd) {ierr = PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]]);CHKERRQ(ierr);} 1157 } 1158 ierr = PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized");CHKERRQ(ierr); 1159 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1160 } 1161 } 1162 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 1163 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 1164 for (l = 0; l < numLabels; ++l) { 1165 DMLabel label; 1166 const char *name; 1167 IS valueIS; 1168 const PetscInt *values; 1169 PetscInt numValues, v; 1170 1171 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 1172 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1173 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 1174 ierr = PetscViewerASCIIPrintf(viewer, " %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr); 1175 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 1176 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 1177 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1178 for (v = 0; v < numValues; ++v) { 1179 PetscInt size; 1180 1181 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 1182 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1183 ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr); 1184 } 1185 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 1186 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1187 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 1188 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 1189 } 1190 { 1191 char **labelNames; 1192 PetscInt Nl = numLabels; 1193 PetscBool flg; 1194 1195 ierr = PetscMalloc1(Nl, &labelNames);CHKERRQ(ierr); 1196 ierr = PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg);CHKERRQ(ierr); 1197 for (l = 0; l < Nl; ++l) { 1198 DMLabel label; 1199 1200 ierr = DMHasLabel(dm, labelNames[l], &flg);CHKERRQ(ierr); 1201 if (flg) { 1202 ierr = DMGetLabel(dm, labelNames[l], &label);CHKERRQ(ierr); 1203 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 1204 } 1205 ierr = PetscFree(labelNames[l]);CHKERRQ(ierr); 1206 } 1207 ierr = PetscFree(labelNames);CHKERRQ(ierr); 1208 } 1209 /* If no fields are specified, people do not want to see adjacency */ 1210 if (dm->Nf) { 1211 PetscInt f; 1212 1213 for (f = 0; f < dm->Nf; ++f) { 1214 const char *name; 1215 1216 ierr = PetscObjectGetName(dm->fields[f].disc, &name);CHKERRQ(ierr); 1217 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Field %s:\n", name);CHKERRQ(ierr);} 1218 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1219 if (dm->fields[f].label) {ierr = DMLabelView(dm->fields[f].label, viewer);CHKERRQ(ierr);} 1220 if (dm->fields[f].adjacency[0]) { 1221 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n");CHKERRQ(ierr);} 1222 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM\n");CHKERRQ(ierr);} 1223 } else { 1224 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FEM\n");CHKERRQ(ierr);} 1225 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n");CHKERRQ(ierr);} 1226 } 1227 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1228 } 1229 } 1230 ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr); 1231 if (cdm) { 1232 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1233 ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr); 1234 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1235 } 1236 } 1237 PetscFunctionReturn(0); 1238 } 1239 1240 static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1241 { 1242 DMPolytopeType ct; 1243 PetscMPIInt rank; 1244 PetscErrorCode ierr; 1245 1246 PetscFunctionBegin; 1247 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1248 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1249 switch (ct) { 1250 case DM_POLYTOPE_TRIANGLE: 1251 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1252 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1253 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1254 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1255 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1256 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1257 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1258 break; 1259 case DM_POLYTOPE_QUADRILATERAL: 1260 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1261 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1262 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1263 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1264 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1265 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1266 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1267 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1268 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1269 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1270 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1271 ierr = PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1272 break; 1273 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1274 } 1275 PetscFunctionReturn(0); 1276 } 1277 1278 static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1279 { 1280 DMPolytopeType ct; 1281 PetscReal centroid[2] = {0., 0.}; 1282 PetscMPIInt rank; 1283 PetscInt fillColor, v, e, d; 1284 PetscErrorCode ierr; 1285 1286 PetscFunctionBegin; 1287 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1288 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1289 fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2; 1290 switch (ct) { 1291 case DM_POLYTOPE_TRIANGLE: 1292 { 1293 PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1294 1295 for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;} 1296 for (e = 0; e < 3; ++e) { 1297 refCoords[0] = refVertices[e*2+0]; 1298 refCoords[1] = refVertices[e*2+1]; 1299 for (d = 1; d <= edgeDiv; ++d) { 1300 refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv; 1301 refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv; 1302 } 1303 ierr = DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords);CHKERRQ(ierr); 1304 for (d = 0; d < edgeDiv; ++d) { 1305 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); 1306 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); 1307 } 1308 } 1309 } 1310 break; 1311 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1312 } 1313 PetscFunctionReturn(0); 1314 } 1315 1316 static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1317 { 1318 PetscDraw draw; 1319 DM cdm; 1320 PetscSection coordSection; 1321 Vec coordinates; 1322 const PetscScalar *coords; 1323 PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1324 PetscReal *refCoords, *edgeCoords; 1325 PetscBool isnull, drawAffine = PETSC_TRUE; 1326 PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1327 PetscErrorCode ierr; 1328 1329 PetscFunctionBegin; 1330 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 1331 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim); 1332 ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL);CHKERRQ(ierr); 1333 if (!drawAffine) {ierr = PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords);CHKERRQ(ierr);} 1334 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 1335 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1336 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 1337 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1338 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1339 1340 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 1341 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 1342 if (isnull) PetscFunctionReturn(0); 1343 ierr = PetscDrawSetTitle(draw, "Mesh");CHKERRQ(ierr); 1344 1345 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 1346 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 1347 for (c = 0; c < N; c += dim) { 1348 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 1349 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1350 } 1351 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 1352 ierr = MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1353 ierr = MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1354 ierr = PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]);CHKERRQ(ierr); 1355 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 1356 1357 for (c = cStart; c < cEnd; ++c) { 1358 PetscScalar *coords = NULL; 1359 PetscInt numCoords; 1360 1361 ierr = DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords);CHKERRQ(ierr); 1362 if (drawAffine) { 1363 ierr = DMPlexDrawCell(dm, draw, c, coords);CHKERRQ(ierr); 1364 } else { 1365 ierr = DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords);CHKERRQ(ierr); 1366 } 1367 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 1368 } 1369 if (!drawAffine) {ierr = PetscFree2(refCoords, edgeCoords);CHKERRQ(ierr);} 1370 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1371 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 1372 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 1373 PetscFunctionReturn(0); 1374 } 1375 1376 #if defined(PETSC_HAVE_EXODUSII) 1377 #include <exodusII.h> 1378 #include <petscviewerexodusii.h> 1379 #endif 1380 1381 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1382 { 1383 PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1384 char name[PETSC_MAX_PATH_LEN]; 1385 PetscErrorCode ierr; 1386 1387 PetscFunctionBegin; 1388 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1389 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1390 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1391 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1392 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1393 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 1394 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 1395 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus);CHKERRQ(ierr); 1396 if (iascii) { 1397 PetscViewerFormat format; 1398 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1399 if (format == PETSC_VIEWER_ASCII_GLVIS) { 1400 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1401 } else { 1402 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 1403 } 1404 } else if (ishdf5) { 1405 #if defined(PETSC_HAVE_HDF5) 1406 ierr = DMPlexView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1407 #else 1408 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1409 #endif 1410 } else if (isvtk) { 1411 ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr); 1412 } else if (isdraw) { 1413 ierr = DMPlexView_Draw(dm, viewer);CHKERRQ(ierr); 1414 } else if (isglvis) { 1415 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1416 #if defined(PETSC_HAVE_EXODUSII) 1417 } else if (isexodus) { 1418 /* 1419 exodusII requires that all sets be part of exactly one cell set. 1420 If the dm does not have a "Cell Sets" label defined, we create one 1421 with ID 1, containig all cells. 1422 Note that if the Cell Sets label is defined but does not cover all cells, 1423 we may still have a problem. This should probably be checked here or in the viewer; 1424 */ 1425 PetscInt numCS; 1426 ierr = DMGetLabelSize(dm,"Cell Sets",&numCS);CHKERRQ(ierr); 1427 if (!numCS) { 1428 PetscInt cStart, cEnd, c; 1429 ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr); 1430 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1431 for (c = cStart; c < cEnd; ++c) {ierr = DMSetLabelValue(dm, "Cell Sets", c, 1);CHKERRQ(ierr);} 1432 } 1433 ierr = DMView_PlexExodusII(dm, viewer);CHKERRQ(ierr); 1434 #endif 1435 } else { 1436 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1437 } 1438 /* Optionally view the partition */ 1439 ierr = PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg);CHKERRQ(ierr); 1440 if (flg) { 1441 Vec ranks; 1442 ierr = DMPlexCreateRankField(dm, &ranks);CHKERRQ(ierr); 1443 ierr = VecView(ranks, viewer);CHKERRQ(ierr); 1444 ierr = VecDestroy(&ranks);CHKERRQ(ierr); 1445 } 1446 /* Optionally view a label */ 1447 ierr = PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg);CHKERRQ(ierr); 1448 if (flg) { 1449 DMLabel label; 1450 Vec val; 1451 1452 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1453 if (!label) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 1454 ierr = DMPlexCreateLabelField(dm, label, &val);CHKERRQ(ierr); 1455 ierr = VecView(val, viewer);CHKERRQ(ierr); 1456 ierr = VecDestroy(&val);CHKERRQ(ierr); 1457 } 1458 PetscFunctionReturn(0); 1459 } 1460 1461 /*@ 1462 DMPlexTopologyView - Saves a DMPlex topology into a file 1463 1464 Collective on DM 1465 1466 Input Parameters: 1467 + dm - The DM whose topology is to be saved 1468 - viewer - The PetscViewer for saving 1469 1470 Level: advanced 1471 1472 .seealso: DMView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexTopologyLoad() 1473 @*/ 1474 PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 1475 { 1476 PetscBool ishdf5; 1477 PetscErrorCode ierr; 1478 1479 PetscFunctionBegin; 1480 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1481 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1482 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1483 if (ishdf5) { 1484 #if defined(PETSC_HAVE_HDF5) 1485 PetscViewerFormat format; 1486 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1487 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1488 IS globalPointNumbering; 1489 1490 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1491 ierr = DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1492 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1493 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 1494 #else 1495 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1496 #endif 1497 } 1498 PetscFunctionReturn(0); 1499 } 1500 1501 /*@ 1502 DMPlexCoordinatesView - Saves DMPlex coordinates into a file 1503 1504 Collective on DM 1505 1506 Input Parameters: 1507 + dm - The DM whose coordinates are to be saved 1508 - viewer - The PetscViewer for saving 1509 1510 Level: advanced 1511 1512 .seealso: DMView(), DMPlexTopologyView(), DMPlexLabelsView(), DMPlexCoordinatesLoad() 1513 @*/ 1514 PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 1515 { 1516 PetscBool ishdf5; 1517 PetscErrorCode ierr; 1518 1519 PetscFunctionBegin; 1520 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1521 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1522 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1523 if (ishdf5) { 1524 #if defined(PETSC_HAVE_HDF5) 1525 PetscViewerFormat format; 1526 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1527 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1528 ierr = DMPlexCoordinatesView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1529 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1530 #else 1531 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1532 #endif 1533 } 1534 PetscFunctionReturn(0); 1535 } 1536 1537 /*@ 1538 DMPlexLabelsView - Saves DMPlex labels into a file 1539 1540 Collective on DM 1541 1542 Input Parameters: 1543 + dm - The DM whose labels are to be saved 1544 - viewer - The PetscViewer for saving 1545 1546 Level: advanced 1547 1548 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsLoad() 1549 @*/ 1550 PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1551 { 1552 PetscBool ishdf5; 1553 PetscErrorCode ierr; 1554 1555 PetscFunctionBegin; 1556 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1557 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1558 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1559 if (ishdf5) { 1560 #if defined(PETSC_HAVE_HDF5) 1561 IS globalPointNumbering; 1562 PetscViewerFormat format; 1563 1564 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1565 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1566 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1567 ierr = DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1568 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1569 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1570 #else 1571 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1572 #endif 1573 } 1574 PetscFunctionReturn(0); 1575 } 1576 1577 /*@ 1578 DMPlexSectionView - Saves a section associated with a DMPlex 1579 1580 Collective on DM 1581 1582 Input Parameters: 1583 + dm - The DM that contains the topology on which the section to be saved is defined 1584 . viewer - The PetscViewer for saving 1585 - sectiondm - The DM that contains the section to be saved 1586 1587 Level: advanced 1588 1589 Notes: 1590 This function is a wrapper around PetscSectionView(); in addition to the raw section, it saves information that associates the section points to the topology (dm) points. When the topology (dm) and the section are later loaded with DMPlexTopologyLoad() and DMPlexSectionLoad(), respectively, this information is used to match section points with topology points. 1591 1592 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 1593 1594 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexGlobalVectorView(), DMPlexLocalVectorView(), PetscSectionView(), DMPlexSectionLoad() 1595 @*/ 1596 PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1597 { 1598 PetscBool ishdf5; 1599 PetscErrorCode ierr; 1600 1601 PetscFunctionBegin; 1602 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1603 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1604 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1605 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 1606 if (ishdf5) { 1607 #if defined(PETSC_HAVE_HDF5) 1608 ierr = DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm);CHKERRQ(ierr); 1609 #else 1610 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1611 #endif 1612 } 1613 PetscFunctionReturn(0); 1614 } 1615 1616 /*@ 1617 DMPlexGlobalVectorView - Saves a global vector 1618 1619 Collective on DM 1620 1621 Input Parameters: 1622 + dm - The DM that represents the topology 1623 . viewer - The PetscViewer to save data with 1624 . sectiondm - The DM that contains the global section on which vec is defined 1625 - vec - The global vector to be saved 1626 1627 Level: advanced 1628 1629 Notes: 1630 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 1631 1632 Typical calling sequence 1633 $ DMCreate(PETSC_COMM_WORLD, &dm); 1634 $ DMSetType(dm, DMPLEX); 1635 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1636 $ DMClone(dm, §iondm); 1637 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1638 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1639 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1640 $ PetscSectionSetChart(section, pStart, pEnd); 1641 $ PetscSectionSetUp(section); 1642 $ DMSetLocalSection(sectiondm, section); 1643 $ PetscSectionDestroy(§ion); 1644 $ DMGetGlobalVector(sectiondm, &vec); 1645 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1646 $ DMPlexTopologyView(dm, viewer); 1647 $ DMPlexSectionView(dm, viewer, sectiondm); 1648 $ DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 1649 $ DMRestoreGlobalVector(sectiondm, &vec); 1650 $ DMDestroy(§iondm); 1651 $ DMDestroy(&dm); 1652 1653 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexLocalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1654 @*/ 1655 PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1656 { 1657 PetscBool ishdf5; 1658 PetscErrorCode ierr; 1659 1660 PetscFunctionBegin; 1661 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1662 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1663 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1664 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1665 /* Check consistency */ 1666 { 1667 PetscSection section; 1668 PetscBool includesConstraints; 1669 PetscInt m, m1; 1670 1671 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1672 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 1673 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1674 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1675 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1676 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 1677 } 1678 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1679 if (ishdf5) { 1680 #if defined(PETSC_HAVE_HDF5) 1681 ierr = DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1682 #else 1683 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1684 #endif 1685 } 1686 PetscFunctionReturn(0); 1687 } 1688 1689 /*@ 1690 DMPlexLocalVectorView - Saves a local vector 1691 1692 Collective on DM 1693 1694 Input Parameters: 1695 + dm - The DM that represents the topology 1696 . viewer - The PetscViewer to save data with 1697 . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm 1698 - vec - The local vector to be saved 1699 1700 Level: advanced 1701 1702 Notes: 1703 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 1704 1705 Typical calling sequence 1706 $ DMCreate(PETSC_COMM_WORLD, &dm); 1707 $ DMSetType(dm, DMPLEX); 1708 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1709 $ DMClone(dm, §iondm); 1710 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1711 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1712 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1713 $ PetscSectionSetChart(section, pStart, pEnd); 1714 $ PetscSectionSetUp(section); 1715 $ DMSetLocalSection(sectiondm, section); 1716 $ DMGetLocalVector(sectiondm, &vec); 1717 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1718 $ DMPlexTopologyView(dm, viewer); 1719 $ DMPlexSectionView(dm, viewer, sectiondm); 1720 $ DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 1721 $ DMRestoreLocalVector(sectiondm, &vec); 1722 $ DMDestroy(§iondm); 1723 $ DMDestroy(&dm); 1724 1725 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexGlobalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1726 @*/ 1727 PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1728 { 1729 PetscBool ishdf5; 1730 PetscErrorCode ierr; 1731 1732 PetscFunctionBegin; 1733 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1734 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1735 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1736 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1737 /* Check consistency */ 1738 { 1739 PetscSection section; 1740 PetscBool includesConstraints; 1741 PetscInt m, m1; 1742 1743 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1744 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 1745 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1746 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1747 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1748 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 1749 } 1750 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1751 if (ishdf5) { 1752 #if defined(PETSC_HAVE_HDF5) 1753 ierr = DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1754 #else 1755 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1756 #endif 1757 } 1758 PetscFunctionReturn(0); 1759 } 1760 1761 PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 1762 { 1763 PetscBool ishdf5; 1764 PetscErrorCode ierr; 1765 1766 PetscFunctionBegin; 1767 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1768 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1769 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1770 if (ishdf5) { 1771 #if defined(PETSC_HAVE_HDF5) 1772 PetscViewerFormat format; 1773 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1774 if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 1775 ierr = DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer);CHKERRQ(ierr); 1776 } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1777 ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1778 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1779 PetscFunctionReturn(0); 1780 #else 1781 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1782 #endif 1783 } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 1784 } 1785 1786 /*@ 1787 DMPlexTopologyLoad - Loads a topology into a DMPlex 1788 1789 Collective on DM 1790 1791 Input Parameters: 1792 + dm - The DM into which the topology is loaded 1793 - viewer - The PetscViewer for the saved topology 1794 1795 Output Parameters: 1796 . globalToLocalPointSF - The PetscSF that pushes points in [0, N) to the associated points in the loaded plex, where N is the global number of points; NULL if unneeded 1797 1798 Level: advanced 1799 1800 .seealso: DMLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1801 @*/ 1802 PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 1803 { 1804 PetscBool ishdf5; 1805 PetscErrorCode ierr; 1806 1807 PetscFunctionBegin; 1808 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1809 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1810 if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 1811 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1812 if (ishdf5) { 1813 #if defined(PETSC_HAVE_HDF5) 1814 PetscViewerFormat format; 1815 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1816 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1817 ierr = DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 1818 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1819 #else 1820 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1821 #endif 1822 } 1823 PetscFunctionReturn(0); 1824 } 1825 1826 /*@ 1827 DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 1828 1829 Collective on DM 1830 1831 Input Parameters: 1832 + dm - The DM into which the coordinates are loaded 1833 - viewer - The PetscViewer for the saved coordinates 1834 1835 Level: advanced 1836 1837 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1838 @*/ 1839 PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer) 1840 { 1841 PetscBool ishdf5; 1842 PetscErrorCode ierr; 1843 1844 PetscFunctionBegin; 1845 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1846 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1847 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1848 if (ishdf5) { 1849 #if defined(PETSC_HAVE_HDF5) 1850 PetscViewerFormat format; 1851 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1852 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1853 ierr = DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1854 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1855 #else 1856 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1857 #endif 1858 } 1859 PetscFunctionReturn(0); 1860 } 1861 1862 /*@ 1863 DMPlexLabelsLoad - Loads labels into a DMPlex 1864 1865 Collective on DM 1866 1867 Input Parameters: 1868 + dm - The DM into which the labels are loaded 1869 - viewer - The PetscViewer for the saved labels 1870 1871 Level: advanced 1872 1873 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1874 @*/ 1875 PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer) 1876 { 1877 PetscBool ishdf5; 1878 PetscErrorCode ierr; 1879 1880 PetscFunctionBegin; 1881 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1882 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1883 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1884 if (ishdf5) { 1885 #if defined(PETSC_HAVE_HDF5) 1886 PetscViewerFormat format; 1887 1888 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1889 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1890 ierr = DMPlexLabelsLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1891 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1892 #else 1893 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1894 #endif 1895 } 1896 PetscFunctionReturn(0); 1897 } 1898 1899 /*@ 1900 DMPlexSectionLoad - Loads section into a DMPlex 1901 1902 Collective on DM 1903 1904 Input Parameters: 1905 + dm - The DM that represents the topology 1906 . viewer - The PetscViewer that represents the on-disk section (sectionA) 1907 . sectiondm - The DM into which the on-disk section (sectionA) is migrated 1908 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 1909 1910 Output Parameters 1911 + globalDofSF - The SF that migrates any on-disk Vec data associated with sectionA into a global Vec associated with the sectiondm's global section (NULL if not needed) 1912 - localDofSF - The SF that migrates any on-disk Vec data associated with sectionA into a local Vec associated with the sectiondm's local section (NULL if not needed) 1913 1914 Level: advanced 1915 1916 Notes: 1917 This function is a wrapper around PetscSectionLoad(); it loads, in addition to the raw section, a list of global point numbers that associates each on-disk section point with a global point number in [0, NX), where NX is the number of topology points in dm. Noting that globalToLocalPointSF associates each topology point in dm with a global number in [0, NX), one can readily establish an association of the on-disk section points with the topology points. 1918 1919 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 1920 1921 The output parameter, globalDofSF (localDofSF), can later be used with DMPlexGlobalVectorLoad() (DMPlexLocalVectorLoad()) to load on-disk vectors into global (local) vectors associated with sectiondm's global (local) section. 1922 1923 Example using 2 processes: 1924 $ NX (number of points on dm): 4 1925 $ sectionA : the on-disk section 1926 $ vecA : a vector associated with sectionA 1927 $ sectionB : sectiondm's local section constructed in this function 1928 $ vecB (local) : a vector associated with sectiondm's local section 1929 $ vecB (global) : a vector associated with sectiondm's global section 1930 $ 1931 $ rank 0 rank 1 1932 $ vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 1933 $ sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 1934 $ sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 1935 $ sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 1936 $ [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 1937 $ sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 1938 $ sectionB->atlasDof : 1 0 1 | 1 3 1939 $ sectionB->atlasOff (no perm) : 0 1 1 | 0 1 1940 $ vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 1941 $ vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 1942 $ 1943 $ where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 1944 1945 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad(), PetscSectionLoad(), DMPlexSectionView() 1946 @*/ 1947 PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 1948 { 1949 PetscBool ishdf5; 1950 PetscErrorCode ierr; 1951 1952 PetscFunctionBegin; 1953 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1954 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1955 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1956 PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 1957 if (globalDofSF) PetscValidPointer(globalDofSF, 5); 1958 if (localDofSF) PetscValidPointer(localDofSF, 6); 1959 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 1960 if (ishdf5) { 1961 #if defined(PETSC_HAVE_HDF5) 1962 ierr = DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF);CHKERRQ(ierr); 1963 #else 1964 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1965 #endif 1966 } 1967 PetscFunctionReturn(0); 1968 } 1969 1970 /*@ 1971 DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 1972 1973 Collective on DM 1974 1975 Input Parameters: 1976 + dm - The DM that represents the topology 1977 . viewer - The PetscViewer that represents the on-disk vector data 1978 . sectiondm - The DM that contains the global section on which vec is defined 1979 . sf - The SF that migrates the on-disk vector data into vec 1980 - vec - The global vector to set values of 1981 1982 Level: advanced 1983 1984 Notes: 1985 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 1986 1987 Typical calling sequence 1988 $ DMCreate(PETSC_COMM_WORLD, &dm); 1989 $ DMSetType(dm, DMPLEX); 1990 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1991 $ DMPlexTopologyLoad(dm, viewer, &sfX); 1992 $ DMClone(dm, §iondm); 1993 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1994 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 1995 $ DMGetGlobalVector(sectiondm, &vec); 1996 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1997 $ DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 1998 $ DMRestoreGlobalVector(sectiondm, &vec); 1999 $ PetscSFDestroy(&gsf); 2000 $ PetscSFDestroy(&sfX); 2001 $ DMDestroy(§iondm); 2002 $ DMDestroy(&dm); 2003 2004 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexLocalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2005 @*/ 2006 PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2007 { 2008 PetscBool ishdf5; 2009 PetscErrorCode ierr; 2010 2011 PetscFunctionBegin; 2012 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2013 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2014 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2015 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2016 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2017 /* Check consistency */ 2018 { 2019 PetscSection section; 2020 PetscBool includesConstraints; 2021 PetscInt m, m1; 2022 2023 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2024 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 2025 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2026 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2027 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2028 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 2029 } 2030 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2031 if (ishdf5) { 2032 #if defined(PETSC_HAVE_HDF5) 2033 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2034 #else 2035 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2036 #endif 2037 } 2038 PetscFunctionReturn(0); 2039 } 2040 2041 /*@ 2042 DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 2043 2044 Collective on DM 2045 2046 Input Parameters: 2047 + dm - The DM that represents the topology 2048 . viewer - The PetscViewer that represents the on-disk vector data 2049 . sectiondm - The DM that contains the local section on which vec is defined 2050 . sf - The SF that migrates the on-disk vector data into vec 2051 - vec - The local vector to set values of 2052 2053 Level: advanced 2054 2055 Notes: 2056 In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2057 2058 Typical calling sequence 2059 $ DMCreate(PETSC_COMM_WORLD, &dm); 2060 $ DMSetType(dm, DMPLEX); 2061 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2062 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2063 $ DMClone(dm, §iondm); 2064 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2065 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2066 $ DMGetLocalVector(sectiondm, &vec); 2067 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2068 $ DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2069 $ DMRestoreLocalVector(sectiondm, &vec); 2070 $ PetscSFDestroy(&lsf); 2071 $ PetscSFDestroy(&sfX); 2072 $ DMDestroy(§iondm); 2073 $ DMDestroy(&dm); 2074 2075 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexGlobalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2076 @*/ 2077 PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2078 { 2079 PetscBool ishdf5; 2080 PetscErrorCode ierr; 2081 2082 PetscFunctionBegin; 2083 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2084 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2085 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2086 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2087 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2088 /* Check consistency */ 2089 { 2090 PetscSection section; 2091 PetscBool includesConstraints; 2092 PetscInt m, m1; 2093 2094 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2095 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 2096 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2097 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2098 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2099 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 2100 } 2101 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2102 if (ishdf5) { 2103 #if defined(PETSC_HAVE_HDF5) 2104 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2105 #else 2106 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2107 #endif 2108 } 2109 PetscFunctionReturn(0); 2110 } 2111 2112 PetscErrorCode DMDestroy_Plex(DM dm) 2113 { 2114 DM_Plex *mesh = (DM_Plex*) dm->data; 2115 PetscErrorCode ierr; 2116 2117 PetscFunctionBegin; 2118 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr); 2119 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr); 2120 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL);CHKERRQ(ierr); 2121 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL);CHKERRQ(ierr); 2122 if (--mesh->refct > 0) PetscFunctionReturn(0); 2123 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 2124 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 2125 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 2126 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 2127 ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr); 2128 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 2129 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 2130 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 2131 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 2132 ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 2133 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 2134 ierr = ISDestroy(&mesh->subpointIS);CHKERRQ(ierr); 2135 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 2136 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 2137 ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 2138 ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 2139 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 2140 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 2141 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 2142 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 2143 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 2144 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 2145 ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr); 2146 ierr = PetscFree(mesh->neighbors);CHKERRQ(ierr); 2147 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 2148 ierr = PetscFree(mesh);CHKERRQ(ierr); 2149 PetscFunctionReturn(0); 2150 } 2151 2152 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2153 { 2154 PetscSection sectionGlobal; 2155 PetscInt bs = -1, mbs; 2156 PetscInt localSize; 2157 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2158 PetscErrorCode ierr; 2159 MatType mtype; 2160 ISLocalToGlobalMapping ltog; 2161 2162 PetscFunctionBegin; 2163 ierr = MatInitializePackage();CHKERRQ(ierr); 2164 mtype = dm->mattype; 2165 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 2166 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 2167 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 2168 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 2169 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 2170 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 2171 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 2172 ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr); 2173 if (mbs > 1) bs = mbs; 2174 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 2175 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 2176 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 2177 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 2178 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 2179 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 2180 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 2181 ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr); 2182 if (!isShell) { 2183 PetscSection subSection; 2184 PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 2185 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *ltogidx, lsize; 2186 PetscInt pStart, pEnd, p, dof, cdof; 2187 2188 /* Set localtoglobalmapping on the matrix for MatSetValuesLocal() to work (it also creates the local matrices in case of MATIS) */ 2189 if (isMatIS) { /* need a different l2g map than the one computed by DMGetLocalToGlobalMapping */ 2190 PetscSection section; 2191 PetscInt size; 2192 2193 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 2194 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 2195 ierr = PetscMalloc1(size,<ogidx);CHKERRQ(ierr); 2196 ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr); 2197 } else { 2198 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 2199 } 2200 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 2201 for (p = pStart, lsize = 0; p < pEnd; ++p) { 2202 PetscInt bdof; 2203 2204 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 2205 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 2206 dof = dof < 0 ? -(dof+1) : dof; 2207 bdof = cdof && (dof-cdof) ? 1 : dof; 2208 if (dof) { 2209 if (bs < 0) {bs = bdof;} 2210 else if (bs != bdof) {bs = 1; if (!isMatIS) break;} 2211 } 2212 if (isMatIS) { 2213 PetscInt loff,c,off; 2214 ierr = PetscSectionGetOffset(subSection, p, &loff);CHKERRQ(ierr); 2215 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 2216 for (c = 0; c < dof-cdof; ++c, ++lsize) ltogidx[loff+c] = off > -1 ? off+c : -(off+1)+c; 2217 } 2218 } 2219 /* Must have same blocksize on all procs (some might have no points) */ 2220 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 2221 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 2222 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 2223 else {bs = bsMinMax[0];} 2224 bs = PetscMax(1,bs); 2225 if (isMatIS) { /* Must reduce indices by blocksize */ 2226 PetscInt l; 2227 2228 lsize = lsize/bs; 2229 if (bs > 1) for (l = 0; l < lsize; ++l) ltogidx[l] = ltogidx[l*bs]/bs; 2230 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, lsize, ltogidx, PETSC_OWN_POINTER, <og);CHKERRQ(ierr); 2231 } 2232 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 2233 if (isMatIS) { 2234 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 2235 } 2236 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 2237 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 2238 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 2239 } 2240 ierr = MatSetDM(*J, dm);CHKERRQ(ierr); 2241 PetscFunctionReturn(0); 2242 } 2243 2244 /*@ 2245 DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2246 2247 Not collective 2248 2249 Input Parameter: 2250 . mesh - The DMPlex 2251 2252 Output Parameters: 2253 . subsection - The subdomain section 2254 2255 Level: developer 2256 2257 .seealso: 2258 @*/ 2259 PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2260 { 2261 DM_Plex *mesh = (DM_Plex*) dm->data; 2262 PetscErrorCode ierr; 2263 2264 PetscFunctionBegin; 2265 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2266 if (!mesh->subdomainSection) { 2267 PetscSection section; 2268 PetscSF sf; 2269 2270 ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr); 2271 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 2272 ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr); 2273 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 2274 } 2275 *subsection = mesh->subdomainSection; 2276 PetscFunctionReturn(0); 2277 } 2278 2279 /*@ 2280 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2281 2282 Not collective 2283 2284 Input Parameter: 2285 . mesh - The DMPlex 2286 2287 Output Parameters: 2288 + pStart - The first mesh point 2289 - pEnd - The upper bound for mesh points 2290 2291 Level: beginner 2292 2293 .seealso: DMPlexCreate(), DMPlexSetChart() 2294 @*/ 2295 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2296 { 2297 DM_Plex *mesh = (DM_Plex*) dm->data; 2298 PetscErrorCode ierr; 2299 2300 PetscFunctionBegin; 2301 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2302 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2303 PetscFunctionReturn(0); 2304 } 2305 2306 /*@ 2307 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2308 2309 Not collective 2310 2311 Input Parameters: 2312 + mesh - The DMPlex 2313 . pStart - The first mesh point 2314 - pEnd - The upper bound for mesh points 2315 2316 Output Parameters: 2317 2318 Level: beginner 2319 2320 .seealso: DMPlexCreate(), DMPlexGetChart() 2321 @*/ 2322 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2323 { 2324 DM_Plex *mesh = (DM_Plex*) dm->data; 2325 PetscErrorCode ierr; 2326 2327 PetscFunctionBegin; 2328 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2329 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2330 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 2331 PetscFunctionReturn(0); 2332 } 2333 2334 /*@ 2335 DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2336 2337 Not collective 2338 2339 Input Parameters: 2340 + mesh - The DMPlex 2341 - p - The point, which must lie in the chart set with DMPlexSetChart() 2342 2343 Output Parameter: 2344 . size - The cone size for point p 2345 2346 Level: beginner 2347 2348 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2349 @*/ 2350 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2351 { 2352 DM_Plex *mesh = (DM_Plex*) dm->data; 2353 PetscErrorCode ierr; 2354 2355 PetscFunctionBegin; 2356 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2357 PetscValidPointer(size, 3); 2358 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2359 PetscFunctionReturn(0); 2360 } 2361 2362 /*@ 2363 DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2364 2365 Not collective 2366 2367 Input Parameters: 2368 + mesh - The DMPlex 2369 . p - The point, which must lie in the chart set with DMPlexSetChart() 2370 - size - The cone size for point p 2371 2372 Output Parameter: 2373 2374 Note: 2375 This should be called after DMPlexSetChart(). 2376 2377 Level: beginner 2378 2379 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 2380 @*/ 2381 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2382 { 2383 DM_Plex *mesh = (DM_Plex*) dm->data; 2384 PetscErrorCode ierr; 2385 2386 PetscFunctionBegin; 2387 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2388 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2389 2390 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 2391 PetscFunctionReturn(0); 2392 } 2393 2394 /*@ 2395 DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2396 2397 Not collective 2398 2399 Input Parameters: 2400 + mesh - The DMPlex 2401 . p - The point, which must lie in the chart set with DMPlexSetChart() 2402 - size - The additional cone size for point p 2403 2404 Output Parameter: 2405 2406 Note: 2407 This should be called after DMPlexSetChart(). 2408 2409 Level: beginner 2410 2411 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 2412 @*/ 2413 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2414 { 2415 DM_Plex *mesh = (DM_Plex*) dm->data; 2416 PetscInt csize; 2417 PetscErrorCode ierr; 2418 2419 PetscFunctionBegin; 2420 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2421 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2422 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 2423 2424 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 2425 PetscFunctionReturn(0); 2426 } 2427 2428 /*@C 2429 DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2430 2431 Not collective 2432 2433 Input Parameters: 2434 + dm - The DMPlex 2435 - p - The point, which must lie in the chart set with DMPlexSetChart() 2436 2437 Output Parameter: 2438 . cone - An array of points which are on the in-edges for point p 2439 2440 Level: beginner 2441 2442 Fortran Notes: 2443 Since it returns an array, this routine is only available in Fortran 90, and you must 2444 include petsc.h90 in your code. 2445 You must also call DMPlexRestoreCone() after you finish using the returned array. 2446 DMPlexRestoreCone() is not needed/available in C. 2447 2448 .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart() 2449 @*/ 2450 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2451 { 2452 DM_Plex *mesh = (DM_Plex*) dm->data; 2453 PetscInt off; 2454 PetscErrorCode ierr; 2455 2456 PetscFunctionBegin; 2457 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2458 PetscValidPointer(cone, 3); 2459 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2460 *cone = &mesh->cones[off]; 2461 PetscFunctionReturn(0); 2462 } 2463 2464 /*@C 2465 DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 2466 2467 Not collective 2468 2469 Input Parameters: 2470 + dm - The DMPlex 2471 - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 2472 2473 Output Parameter: 2474 + pConesSection - PetscSection describing the layout of pCones 2475 - pCones - An array of points which are on the in-edges for the point set p 2476 2477 Level: intermediate 2478 2479 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart() 2480 @*/ 2481 PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 2482 { 2483 PetscSection cs, newcs; 2484 PetscInt *cones; 2485 PetscInt *newarr=NULL; 2486 PetscInt n; 2487 PetscErrorCode ierr; 2488 2489 PetscFunctionBegin; 2490 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 2491 ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr); 2492 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 2493 if (pConesSection) *pConesSection = newcs; 2494 if (pCones) { 2495 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 2496 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr); 2497 } 2498 PetscFunctionReturn(0); 2499 } 2500 2501 /*@ 2502 DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2503 2504 Not collective 2505 2506 Input Parameters: 2507 + dm - The DMPlex 2508 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2509 2510 Output Parameter: 2511 . expandedPoints - An array of vertices recursively expanded from input points 2512 2513 Level: advanced 2514 2515 Notes: 2516 Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2517 There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2518 2519 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth() 2520 @*/ 2521 PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2522 { 2523 IS *expandedPointsAll; 2524 PetscInt depth; 2525 PetscErrorCode ierr; 2526 2527 PetscFunctionBegin; 2528 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2529 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2530 PetscValidPointer(expandedPoints, 3); 2531 ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2532 *expandedPoints = expandedPointsAll[0]; 2533 ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]);CHKERRQ(ierr); 2534 ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2535 PetscFunctionReturn(0); 2536 } 2537 2538 /*@ 2539 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). 2540 2541 Not collective 2542 2543 Input Parameters: 2544 + dm - The DMPlex 2545 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2546 2547 Output Parameter: 2548 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2549 . expandedPoints - (optional) An array of index sets with recursively expanded cones 2550 - sections - (optional) An array of sections which describe mappings from points to their cone points 2551 2552 Level: advanced 2553 2554 Notes: 2555 Like DMPlexGetConeTuple() but recursive. 2556 2557 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. 2558 For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2559 2560 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: 2561 (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2562 (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2563 2564 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2565 @*/ 2566 PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2567 { 2568 const PetscInt *arr0=NULL, *cone=NULL; 2569 PetscInt *arr=NULL, *newarr=NULL; 2570 PetscInt d, depth_, i, n, newn, cn, co, start, end; 2571 IS *expandedPoints_; 2572 PetscSection *sections_; 2573 PetscErrorCode ierr; 2574 2575 PetscFunctionBegin; 2576 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2577 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2578 if (depth) PetscValidIntPointer(depth, 3); 2579 if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2580 if (sections) PetscValidPointer(sections, 5); 2581 ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr); 2582 ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr); 2583 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2584 ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr); 2585 ierr = PetscCalloc1(depth_, §ions_);CHKERRQ(ierr); 2586 arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2587 for (d=depth_-1; d>=0; d--) { 2588 ierr = PetscSectionCreate(PETSC_COMM_SELF, §ions_[d]);CHKERRQ(ierr); 2589 ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr); 2590 for (i=0; i<n; i++) { 2591 ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr); 2592 if (arr[i] >= start && arr[i] < end) { 2593 ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr); 2594 ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr); 2595 } else { 2596 ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr); 2597 } 2598 } 2599 ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr); 2600 ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr); 2601 ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr); 2602 for (i=0; i<n; i++) { 2603 ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr); 2604 ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr); 2605 if (cn > 1) { 2606 ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr); 2607 ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr); 2608 } else { 2609 newarr[co] = arr[i]; 2610 } 2611 } 2612 ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr); 2613 arr = newarr; 2614 n = newn; 2615 } 2616 ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr); 2617 *depth = depth_; 2618 if (expandedPoints) *expandedPoints = expandedPoints_; 2619 else { 2620 for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);} 2621 ierr = PetscFree(expandedPoints_);CHKERRQ(ierr); 2622 } 2623 if (sections) *sections = sections_; 2624 else { 2625 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(§ions_[d]);CHKERRQ(ierr);} 2626 ierr = PetscFree(sections_);CHKERRQ(ierr); 2627 } 2628 PetscFunctionReturn(0); 2629 } 2630 2631 /*@ 2632 DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2633 2634 Not collective 2635 2636 Input Parameters: 2637 + dm - The DMPlex 2638 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2639 2640 Output Parameter: 2641 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2642 . expandedPoints - (optional) An array of recursively expanded cones 2643 - sections - (optional) An array of sections which describe mappings from points to their cone points 2644 2645 Level: advanced 2646 2647 Notes: 2648 See DMPlexGetConeRecursive() for details. 2649 2650 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2651 @*/ 2652 PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2653 { 2654 PetscInt d, depth_; 2655 PetscErrorCode ierr; 2656 2657 PetscFunctionBegin; 2658 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2659 if (depth && *depth != depth_) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2660 if (depth) *depth = 0; 2661 if (expandedPoints) { 2662 for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);} 2663 ierr = PetscFree(*expandedPoints);CHKERRQ(ierr); 2664 } 2665 if (sections) { 2666 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);} 2667 ierr = PetscFree(*sections);CHKERRQ(ierr); 2668 } 2669 PetscFunctionReturn(0); 2670 } 2671 2672 /*@ 2673 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 2674 2675 Not collective 2676 2677 Input Parameters: 2678 + mesh - The DMPlex 2679 . p - The point, which must lie in the chart set with DMPlexSetChart() 2680 - cone - An array of points which are on the in-edges for point p 2681 2682 Output Parameter: 2683 2684 Note: 2685 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2686 2687 Developer Note: Why not call this DMPlexSetCover() 2688 2689 Level: beginner 2690 2691 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize() 2692 @*/ 2693 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 2694 { 2695 DM_Plex *mesh = (DM_Plex*) dm->data; 2696 PetscInt pStart, pEnd; 2697 PetscInt dof, off, c; 2698 PetscErrorCode ierr; 2699 2700 PetscFunctionBegin; 2701 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2702 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2703 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2704 if (dof) PetscValidPointer(cone, 3); 2705 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2706 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); 2707 for (c = 0; c < dof; ++c) { 2708 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); 2709 mesh->cones[off+c] = cone[c]; 2710 } 2711 PetscFunctionReturn(0); 2712 } 2713 2714 /*@C 2715 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 2716 2717 Not collective 2718 2719 Input Parameters: 2720 + mesh - The DMPlex 2721 - p - The point, which must lie in the chart set with DMPlexSetChart() 2722 2723 Output Parameter: 2724 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2725 integer giving the prescription for cone traversal. If it is negative, the cone is 2726 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 2727 the index of the cone point on which to start. 2728 2729 Level: beginner 2730 2731 Fortran Notes: 2732 Since it returns an array, this routine is only available in Fortran 90, and you must 2733 include petsc.h90 in your code. 2734 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 2735 DMPlexRestoreConeOrientation() is not needed/available in C. 2736 2737 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 2738 @*/ 2739 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 2740 { 2741 DM_Plex *mesh = (DM_Plex*) dm->data; 2742 PetscInt off; 2743 PetscErrorCode ierr; 2744 2745 PetscFunctionBegin; 2746 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2747 if (PetscDefined(USE_DEBUG)) { 2748 PetscInt dof; 2749 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2750 if (dof) PetscValidPointer(coneOrientation, 3); 2751 } 2752 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2753 2754 *coneOrientation = &mesh->coneOrientations[off]; 2755 PetscFunctionReturn(0); 2756 } 2757 2758 /*@ 2759 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 2760 2761 Not collective 2762 2763 Input Parameters: 2764 + mesh - The DMPlex 2765 . p - The point, which must lie in the chart set with DMPlexSetChart() 2766 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2767 integer giving the prescription for cone traversal. If it is negative, the cone is 2768 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 2769 the index of the cone point on which to start. 2770 2771 Output Parameter: 2772 2773 Note: 2774 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2775 2776 Level: beginner 2777 2778 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2779 @*/ 2780 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 2781 { 2782 DM_Plex *mesh = (DM_Plex*) dm->data; 2783 PetscInt pStart, pEnd; 2784 PetscInt dof, off, c; 2785 PetscErrorCode ierr; 2786 2787 PetscFunctionBegin; 2788 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2789 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2790 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2791 if (dof) PetscValidPointer(coneOrientation, 3); 2792 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2793 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); 2794 for (c = 0; c < dof; ++c) { 2795 PetscInt cdof, o = coneOrientation[c]; 2796 2797 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 2798 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); 2799 mesh->coneOrientations[off+c] = o; 2800 } 2801 PetscFunctionReturn(0); 2802 } 2803 2804 /*@ 2805 DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 2806 2807 Not collective 2808 2809 Input Parameters: 2810 + mesh - The DMPlex 2811 . p - The point, which must lie in the chart set with DMPlexSetChart() 2812 . conePos - The local index in the cone where the point should be put 2813 - conePoint - The mesh point to insert 2814 2815 Level: beginner 2816 2817 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2818 @*/ 2819 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 2820 { 2821 DM_Plex *mesh = (DM_Plex*) dm->data; 2822 PetscInt pStart, pEnd; 2823 PetscInt dof, off; 2824 PetscErrorCode ierr; 2825 2826 PetscFunctionBegin; 2827 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2828 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2829 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); 2830 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); 2831 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2832 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2833 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); 2834 mesh->cones[off+conePos] = conePoint; 2835 PetscFunctionReturn(0); 2836 } 2837 2838 /*@ 2839 DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 2840 2841 Not collective 2842 2843 Input Parameters: 2844 + mesh - The DMPlex 2845 . p - The point, which must lie in the chart set with DMPlexSetChart() 2846 . conePos - The local index in the cone where the point should be put 2847 - coneOrientation - The point orientation to insert 2848 2849 Level: beginner 2850 2851 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2852 @*/ 2853 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 2854 { 2855 DM_Plex *mesh = (DM_Plex*) dm->data; 2856 PetscInt pStart, pEnd; 2857 PetscInt dof, off; 2858 PetscErrorCode ierr; 2859 2860 PetscFunctionBegin; 2861 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2862 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2863 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); 2864 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2865 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2866 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); 2867 mesh->coneOrientations[off+conePos] = coneOrientation; 2868 PetscFunctionReturn(0); 2869 } 2870 2871 /*@ 2872 DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 2873 2874 Not collective 2875 2876 Input Parameters: 2877 + mesh - The DMPlex 2878 - p - The point, which must lie in the chart set with DMPlexSetChart() 2879 2880 Output Parameter: 2881 . size - The support size for point p 2882 2883 Level: beginner 2884 2885 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 2886 @*/ 2887 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 2888 { 2889 DM_Plex *mesh = (DM_Plex*) dm->data; 2890 PetscErrorCode ierr; 2891 2892 PetscFunctionBegin; 2893 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2894 PetscValidPointer(size, 3); 2895 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 2896 PetscFunctionReturn(0); 2897 } 2898 2899 /*@ 2900 DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 2901 2902 Not collective 2903 2904 Input Parameters: 2905 + mesh - The DMPlex 2906 . p - The point, which must lie in the chart set with DMPlexSetChart() 2907 - size - The support size for point p 2908 2909 Output Parameter: 2910 2911 Note: 2912 This should be called after DMPlexSetChart(). 2913 2914 Level: beginner 2915 2916 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 2917 @*/ 2918 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 2919 { 2920 DM_Plex *mesh = (DM_Plex*) dm->data; 2921 PetscErrorCode ierr; 2922 2923 PetscFunctionBegin; 2924 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2925 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 2926 2927 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 2928 PetscFunctionReturn(0); 2929 } 2930 2931 /*@C 2932 DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 2933 2934 Not collective 2935 2936 Input Parameters: 2937 + mesh - The DMPlex 2938 - p - The point, which must lie in the chart set with DMPlexSetChart() 2939 2940 Output Parameter: 2941 . support - An array of points which are on the out-edges for point p 2942 2943 Level: beginner 2944 2945 Fortran Notes: 2946 Since it returns an array, this routine is only available in Fortran 90, and you must 2947 include petsc.h90 in your code. 2948 You must also call DMPlexRestoreSupport() after you finish using the returned array. 2949 DMPlexRestoreSupport() is not needed/available in C. 2950 2951 .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart() 2952 @*/ 2953 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 2954 { 2955 DM_Plex *mesh = (DM_Plex*) dm->data; 2956 PetscInt off; 2957 PetscErrorCode ierr; 2958 2959 PetscFunctionBegin; 2960 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2961 PetscValidPointer(support, 3); 2962 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 2963 *support = &mesh->supports[off]; 2964 PetscFunctionReturn(0); 2965 } 2966 2967 /*@ 2968 DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 2969 2970 Not collective 2971 2972 Input Parameters: 2973 + mesh - The DMPlex 2974 . p - The point, which must lie in the chart set with DMPlexSetChart() 2975 - support - An array of points which are on the out-edges for point p 2976 2977 Output Parameter: 2978 2979 Note: 2980 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 2981 2982 Level: beginner 2983 2984 .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 2985 @*/ 2986 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 2987 { 2988 DM_Plex *mesh = (DM_Plex*) dm->data; 2989 PetscInt pStart, pEnd; 2990 PetscInt dof, off, c; 2991 PetscErrorCode ierr; 2992 2993 PetscFunctionBegin; 2994 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2995 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 2996 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 2997 if (dof) PetscValidPointer(support, 3); 2998 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 2999 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); 3000 for (c = 0; c < dof; ++c) { 3001 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); 3002 mesh->supports[off+c] = support[c]; 3003 } 3004 PetscFunctionReturn(0); 3005 } 3006 3007 /*@ 3008 DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 3009 3010 Not collective 3011 3012 Input Parameters: 3013 + mesh - The DMPlex 3014 . p - The point, which must lie in the chart set with DMPlexSetChart() 3015 . supportPos - The local index in the cone where the point should be put 3016 - supportPoint - The mesh point to insert 3017 3018 Level: beginner 3019 3020 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3021 @*/ 3022 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3023 { 3024 DM_Plex *mesh = (DM_Plex*) dm->data; 3025 PetscInt pStart, pEnd; 3026 PetscInt dof, off; 3027 PetscErrorCode ierr; 3028 3029 PetscFunctionBegin; 3030 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3031 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3032 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3033 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3034 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); 3035 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); 3036 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); 3037 mesh->supports[off+supportPos] = supportPoint; 3038 PetscFunctionReturn(0); 3039 } 3040 3041 /*@C 3042 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3043 3044 Not collective 3045 3046 Input Parameters: 3047 + mesh - The DMPlex 3048 . p - The point, which must lie in the chart set with DMPlexSetChart() 3049 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 3050 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 3051 3052 Output Parameters: 3053 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3054 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3055 3056 Note: 3057 If using internal storage (points is NULL on input), each call overwrites the last output. 3058 3059 Fortran Notes: 3060 Since it returns an array, this routine is only available in Fortran 90, and you must 3061 include petsc.h90 in your code. 3062 3063 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3064 3065 Level: beginner 3066 3067 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3068 @*/ 3069 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3070 { 3071 DM_Plex *mesh = (DM_Plex*) dm->data; 3072 PetscInt *closure, *fifo; 3073 const PetscInt *tmp = NULL, *tmpO = NULL; 3074 PetscInt tmpSize, t; 3075 PetscInt depth = 0, maxSize; 3076 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 3077 PetscErrorCode ierr; 3078 3079 PetscFunctionBegin; 3080 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3081 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3082 /* This is only 1-level */ 3083 if (useCone) { 3084 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 3085 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 3086 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 3087 } else { 3088 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 3089 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 3090 } 3091 if (depth == 1) { 3092 if (*points) { 3093 closure = *points; 3094 } else { 3095 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 3096 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 3097 } 3098 closure[0] = p; closure[1] = 0; 3099 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 3100 closure[closureSize] = tmp[t]; 3101 closure[closureSize+1] = tmpO ? tmpO[t] : 0; 3102 } 3103 if (numPoints) *numPoints = closureSize/2; 3104 if (points) *points = closure; 3105 PetscFunctionReturn(0); 3106 } 3107 { 3108 PetscInt c, coneSeries, s,supportSeries; 3109 3110 c = mesh->maxConeSize; 3111 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 3112 s = mesh->maxSupportSize; 3113 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 3114 maxSize = 2*PetscMax(coneSeries,supportSeries); 3115 } 3116 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3117 if (*points) { 3118 closure = *points; 3119 } else { 3120 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 3121 } 3122 closure[0] = p; closure[1] = 0; 3123 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 3124 const PetscInt cp = tmp[t]; 3125 const PetscInt co = tmpO ? tmpO[t] : 0; 3126 3127 closure[closureSize] = cp; 3128 closure[closureSize+1] = co; 3129 fifo[fifoSize] = cp; 3130 fifo[fifoSize+1] = co; 3131 } 3132 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3133 while (fifoSize - fifoStart) { 3134 const PetscInt q = fifo[fifoStart]; 3135 const PetscInt o = fifo[fifoStart+1]; 3136 const PetscInt rev = o >= 0 ? 0 : 1; 3137 const PetscInt off = rev ? -(o+1) : o; 3138 3139 if (useCone) { 3140 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 3141 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 3142 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 3143 } else { 3144 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 3145 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 3146 tmpO = NULL; 3147 } 3148 for (t = 0; t < tmpSize; ++t) { 3149 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 3150 const PetscInt cp = tmp[i]; 3151 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 3152 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 3153 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 3154 PetscInt co = tmpO ? tmpO[i] : 0; 3155 PetscInt c; 3156 3157 if (rev) { 3158 PetscInt childSize, coff; 3159 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 3160 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 3161 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 3162 } 3163 /* Check for duplicate */ 3164 for (c = 0; c < closureSize; c += 2) { 3165 if (closure[c] == cp) break; 3166 } 3167 if (c == closureSize) { 3168 closure[closureSize] = cp; 3169 closure[closureSize+1] = co; 3170 fifo[fifoSize] = cp; 3171 fifo[fifoSize+1] = co; 3172 closureSize += 2; 3173 fifoSize += 2; 3174 } 3175 } 3176 fifoStart += 2; 3177 } 3178 if (numPoints) *numPoints = closureSize/2; 3179 if (points) *points = closure; 3180 ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3181 PetscFunctionReturn(0); 3182 } 3183 3184 /*@C 3185 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 3186 3187 Not collective 3188 3189 Input Parameters: 3190 + mesh - The DMPlex 3191 . p - The point, which must lie in the chart set with DMPlexSetChart() 3192 . orientation - The orientation of the point 3193 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 3194 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 3195 3196 Output Parameters: 3197 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3198 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3199 3200 Note: 3201 If using internal storage (points is NULL on input), each call overwrites the last output. 3202 3203 Fortran Notes: 3204 Since it returns an array, this routine is only available in Fortran 90, and you must 3205 include petsc.h90 in your code. 3206 3207 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3208 3209 Level: beginner 3210 3211 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3212 @*/ 3213 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3214 { 3215 DM_Plex *mesh = (DM_Plex*) dm->data; 3216 PetscInt *closure, *fifo; 3217 const PetscInt *tmp = NULL, *tmpO = NULL; 3218 PetscInt tmpSize, t; 3219 PetscInt depth = 0, maxSize; 3220 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 3221 PetscErrorCode ierr; 3222 3223 PetscFunctionBegin; 3224 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3225 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3226 /* This is only 1-level */ 3227 if (useCone) { 3228 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 3229 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 3230 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 3231 } else { 3232 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 3233 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 3234 } 3235 if (depth == 1) { 3236 if (*points) { 3237 closure = *points; 3238 } else { 3239 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 3240 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 3241 } 3242 closure[0] = p; closure[1] = ornt; 3243 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 3244 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 3245 closure[closureSize] = tmp[i]; 3246 closure[closureSize+1] = tmpO ? tmpO[i] : 0; 3247 } 3248 if (numPoints) *numPoints = closureSize/2; 3249 if (points) *points = closure; 3250 PetscFunctionReturn(0); 3251 } 3252 { 3253 PetscInt c, coneSeries, s,supportSeries; 3254 3255 c = mesh->maxConeSize; 3256 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 3257 s = mesh->maxSupportSize; 3258 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 3259 maxSize = 2*PetscMax(coneSeries,supportSeries); 3260 } 3261 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3262 if (*points) { 3263 closure = *points; 3264 } else { 3265 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 3266 } 3267 closure[0] = p; closure[1] = ornt; 3268 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 3269 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 3270 const PetscInt cp = tmp[i]; 3271 PetscInt co = tmpO ? tmpO[i] : 0; 3272 3273 if (ornt < 0) { 3274 PetscInt childSize, coff; 3275 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 3276 coff = co < 0 ? -(tmpO[i]+1) : tmpO[i]; 3277 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 3278 } 3279 closure[closureSize] = cp; 3280 closure[closureSize+1] = co; 3281 fifo[fifoSize] = cp; 3282 fifo[fifoSize+1] = co; 3283 } 3284 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3285 while (fifoSize - fifoStart) { 3286 const PetscInt q = fifo[fifoStart]; 3287 const PetscInt o = fifo[fifoStart+1]; 3288 const PetscInt rev = o >= 0 ? 0 : 1; 3289 const PetscInt off = rev ? -(o+1) : o; 3290 3291 if (useCone) { 3292 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 3293 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 3294 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 3295 } else { 3296 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 3297 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 3298 tmpO = NULL; 3299 } 3300 for (t = 0; t < tmpSize; ++t) { 3301 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 3302 const PetscInt cp = tmp[i]; 3303 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 3304 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 3305 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 3306 PetscInt co = tmpO ? tmpO[i] : 0; 3307 PetscInt c; 3308 3309 if (rev) { 3310 PetscInt childSize, coff; 3311 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 3312 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 3313 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 3314 } 3315 /* Check for duplicate */ 3316 for (c = 0; c < closureSize; c += 2) { 3317 if (closure[c] == cp) break; 3318 } 3319 if (c == closureSize) { 3320 closure[closureSize] = cp; 3321 closure[closureSize+1] = co; 3322 fifo[fifoSize] = cp; 3323 fifo[fifoSize+1] = co; 3324 closureSize += 2; 3325 fifoSize += 2; 3326 } 3327 } 3328 fifoStart += 2; 3329 } 3330 if (numPoints) *numPoints = closureSize/2; 3331 if (points) *points = closure; 3332 ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3333 PetscFunctionReturn(0); 3334 } 3335 3336 /*@C 3337 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3338 3339 Not collective 3340 3341 Input Parameters: 3342 + mesh - The DMPlex 3343 . p - The point, which must lie in the chart set with DMPlexSetChart() 3344 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 3345 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints, zeroed on exit 3346 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...], zeroed on exit 3347 3348 Note: 3349 If not using internal storage (points is not NULL on input), this call is unnecessary 3350 3351 Fortran Notes: 3352 Since it returns an array, this routine is only available in Fortran 90, and you must 3353 include petsc.h90 in your code. 3354 3355 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3356 3357 Level: beginner 3358 3359 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3360 @*/ 3361 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3362 { 3363 PetscErrorCode ierr; 3364 3365 PetscFunctionBegin; 3366 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3367 if (numPoints) PetscValidIntPointer(numPoints,4); 3368 if (points) PetscValidPointer(points,5); 3369 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr); 3370 if (numPoints) *numPoints = 0; 3371 PetscFunctionReturn(0); 3372 } 3373 3374 /*@ 3375 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3376 3377 Not collective 3378 3379 Input Parameter: 3380 . mesh - The DMPlex 3381 3382 Output Parameters: 3383 + maxConeSize - The maximum number of in-edges 3384 - maxSupportSize - The maximum number of out-edges 3385 3386 Level: beginner 3387 3388 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 3389 @*/ 3390 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3391 { 3392 DM_Plex *mesh = (DM_Plex*) dm->data; 3393 3394 PetscFunctionBegin; 3395 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3396 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 3397 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 3398 PetscFunctionReturn(0); 3399 } 3400 3401 PetscErrorCode DMSetUp_Plex(DM dm) 3402 { 3403 DM_Plex *mesh = (DM_Plex*) dm->data; 3404 PetscInt size; 3405 PetscErrorCode ierr; 3406 3407 PetscFunctionBegin; 3408 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3409 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 3410 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 3411 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 3412 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 3413 ierr = PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt));CHKERRQ(ierr); 3414 if (mesh->maxSupportSize) { 3415 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3416 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 3417 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 3418 ierr = PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt));CHKERRQ(ierr); 3419 } 3420 PetscFunctionReturn(0); 3421 } 3422 3423 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3424 { 3425 PetscErrorCode ierr; 3426 3427 PetscFunctionBegin; 3428 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 3429 ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 3430 if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3431 if (dm->useNatural && dm->sfMigration) { 3432 PetscSF sfMigrationInv,sfNatural; 3433 PetscSection section, sectionSeq; 3434 3435 (*subdm)->sfMigration = dm->sfMigration; 3436 ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr); 3437 ierr = DMGetLocalSection((*subdm), §ion);CHKERRQ(ierr); 3438 ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3439 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq);CHKERRQ(ierr); 3440 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3441 3442 ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3443 (*subdm)->sfNatural = sfNatural; 3444 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3445 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3446 } 3447 PetscFunctionReturn(0); 3448 } 3449 3450 PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 3451 { 3452 PetscErrorCode ierr; 3453 PetscInt i = 0; 3454 3455 PetscFunctionBegin; 3456 ierr = DMClone(dms[0], superdm);CHKERRQ(ierr); 3457 ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr); 3458 (*superdm)->useNatural = PETSC_FALSE; 3459 for (i = 0; i < len; i++) { 3460 if (dms[i]->useNatural && dms[i]->sfMigration) { 3461 PetscSF sfMigrationInv,sfNatural; 3462 PetscSection section, sectionSeq; 3463 3464 (*superdm)->sfMigration = dms[i]->sfMigration; 3465 ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr); 3466 (*superdm)->useNatural = PETSC_TRUE; 3467 ierr = DMGetLocalSection((*superdm), §ion);CHKERRQ(ierr); 3468 ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3469 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq);CHKERRQ(ierr); 3470 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3471 3472 ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3473 (*superdm)->sfNatural = sfNatural; 3474 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3475 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3476 break; 3477 } 3478 } 3479 PetscFunctionReturn(0); 3480 } 3481 3482 /*@ 3483 DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3484 3485 Not collective 3486 3487 Input Parameter: 3488 . mesh - The DMPlex 3489 3490 Output Parameter: 3491 3492 Note: 3493 This should be called after all calls to DMPlexSetCone() 3494 3495 Level: beginner 3496 3497 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 3498 @*/ 3499 PetscErrorCode DMPlexSymmetrize(DM dm) 3500 { 3501 DM_Plex *mesh = (DM_Plex*) dm->data; 3502 PetscInt *offsets; 3503 PetscInt supportSize; 3504 PetscInt pStart, pEnd, p; 3505 PetscErrorCode ierr; 3506 3507 PetscFunctionBegin; 3508 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3509 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 3510 ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3511 /* Calculate support sizes */ 3512 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3513 for (p = pStart; p < pEnd; ++p) { 3514 PetscInt dof, off, c; 3515 3516 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3517 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3518 for (c = off; c < off+dof; ++c) { 3519 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 3520 } 3521 } 3522 for (p = pStart; p < pEnd; ++p) { 3523 PetscInt dof; 3524 3525 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3526 3527 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 3528 } 3529 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3530 /* Calculate supports */ 3531 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 3532 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 3533 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 3534 for (p = pStart; p < pEnd; ++p) { 3535 PetscInt dof, off, c; 3536 3537 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3538 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3539 for (c = off; c < off+dof; ++c) { 3540 const PetscInt q = mesh->cones[c]; 3541 PetscInt offS; 3542 3543 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 3544 3545 mesh->supports[offS+offsets[q]] = p; 3546 ++offsets[q]; 3547 } 3548 } 3549 ierr = PetscFree(offsets);CHKERRQ(ierr); 3550 ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3551 PetscFunctionReturn(0); 3552 } 3553 3554 static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3555 { 3556 IS stratumIS; 3557 PetscErrorCode ierr; 3558 3559 PetscFunctionBegin; 3560 if (pStart >= pEnd) PetscFunctionReturn(0); 3561 if (PetscDefined(USE_DEBUG)) { 3562 PetscInt qStart, qEnd, numLevels, level; 3563 PetscBool overlap = PETSC_FALSE; 3564 ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr); 3565 for (level = 0; level < numLevels; level++) { 3566 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3567 if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3568 } 3569 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); 3570 } 3571 ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr); 3572 ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr); 3573 ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 3574 PetscFunctionReturn(0); 3575 } 3576 3577 /*@ 3578 DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 3579 can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3580 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3581 the DAG. 3582 3583 Collective on dm 3584 3585 Input Parameter: 3586 . mesh - The DMPlex 3587 3588 Output Parameter: 3589 3590 Notes: 3591 Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3592 meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 3593 until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3594 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3595 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3596 3597 The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3598 if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3599 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 3600 to interpolate only that one (e0), so that 3601 $ cone(c0) = {e0, v2} 3602 $ cone(e0) = {v0, v1} 3603 If DMPlexStratify() is run on this mesh, it will give depths 3604 $ depth 0 = {v0, v1, v2} 3605 $ depth 1 = {e0, c0} 3606 where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3607 3608 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3609 3610 Level: beginner 3611 3612 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes() 3613 @*/ 3614 PetscErrorCode DMPlexStratify(DM dm) 3615 { 3616 DM_Plex *mesh = (DM_Plex*) dm->data; 3617 DMLabel label; 3618 PetscInt pStart, pEnd, p; 3619 PetscInt numRoots = 0, numLeaves = 0; 3620 PetscErrorCode ierr; 3621 3622 PetscFunctionBegin; 3623 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3624 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3625 3626 /* Create depth label */ 3627 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3628 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 3629 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3630 3631 { 3632 /* Initialize roots and count leaves */ 3633 PetscInt sMin = PETSC_MAX_INT; 3634 PetscInt sMax = PETSC_MIN_INT; 3635 PetscInt coneSize, supportSize; 3636 3637 for (p = pStart; p < pEnd; ++p) { 3638 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3639 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3640 if (!coneSize && supportSize) { 3641 sMin = PetscMin(p, sMin); 3642 sMax = PetscMax(p, sMax); 3643 ++numRoots; 3644 } else if (!supportSize && coneSize) { 3645 ++numLeaves; 3646 } else if (!supportSize && !coneSize) { 3647 /* Isolated points */ 3648 sMin = PetscMin(p, sMin); 3649 sMax = PetscMax(p, sMax); 3650 } 3651 } 3652 ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr); 3653 } 3654 3655 if (numRoots + numLeaves == (pEnd - pStart)) { 3656 PetscInt sMin = PETSC_MAX_INT; 3657 PetscInt sMax = PETSC_MIN_INT; 3658 PetscInt coneSize, supportSize; 3659 3660 for (p = pStart; p < pEnd; ++p) { 3661 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3662 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3663 if (!supportSize && coneSize) { 3664 sMin = PetscMin(p, sMin); 3665 sMax = PetscMax(p, sMax); 3666 } 3667 } 3668 ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr); 3669 } else { 3670 PetscInt level = 0; 3671 PetscInt qStart, qEnd, q; 3672 3673 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3674 while (qEnd > qStart) { 3675 PetscInt sMin = PETSC_MAX_INT; 3676 PetscInt sMax = PETSC_MIN_INT; 3677 3678 for (q = qStart; q < qEnd; ++q) { 3679 const PetscInt *support; 3680 PetscInt supportSize, s; 3681 3682 ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr); 3683 ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr); 3684 for (s = 0; s < supportSize; ++s) { 3685 sMin = PetscMin(support[s], sMin); 3686 sMax = PetscMax(support[s], sMax); 3687 } 3688 } 3689 ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr); 3690 ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr); 3691 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3692 } 3693 } 3694 { /* just in case there is an empty process */ 3695 PetscInt numValues, maxValues = 0, v; 3696 3697 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 3698 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 3699 for (v = numValues; v < maxValues; v++) { 3700 ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr); 3701 } 3702 } 3703 ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr); 3704 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3705 PetscFunctionReturn(0); 3706 } 3707 3708 PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 3709 { 3710 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3711 PetscInt dim, depth, pheight, coneSize; 3712 PetscErrorCode ierr; 3713 3714 PetscFunctionBeginHot; 3715 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3716 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3717 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3718 pheight = depth - pdepth; 3719 if (depth <= 1) { 3720 switch (pdepth) { 3721 case 0: ct = DM_POLYTOPE_POINT;break; 3722 case 1: 3723 switch (coneSize) { 3724 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3725 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3726 case 4: 3727 switch (dim) { 3728 case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 3729 case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 3730 default: break; 3731 } 3732 break; 3733 case 5: ct = DM_POLYTOPE_PYRAMID;break; 3734 case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3735 case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 3736 default: break; 3737 } 3738 } 3739 } else { 3740 if (pdepth == 0) { 3741 ct = DM_POLYTOPE_POINT; 3742 } else if (pheight == 0) { 3743 switch (dim) { 3744 case 1: 3745 switch (coneSize) { 3746 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3747 default: break; 3748 } 3749 break; 3750 case 2: 3751 switch (coneSize) { 3752 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3753 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3754 default: break; 3755 } 3756 break; 3757 case 3: 3758 switch (coneSize) { 3759 case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 3760 case 5: 3761 { 3762 const PetscInt *cone; 3763 PetscInt faceConeSize; 3764 3765 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 3766 ierr = DMPlexGetConeSize(dm, cone[0], &faceConeSize);CHKERRQ(ierr); 3767 switch (faceConeSize) { 3768 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3769 case 4: ct = DM_POLYTOPE_PYRAMID;break; 3770 } 3771 } 3772 break; 3773 case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 3774 default: break; 3775 } 3776 break; 3777 default: break; 3778 } 3779 } else if (pheight > 0) { 3780 switch (coneSize) { 3781 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3782 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3783 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3784 default: break; 3785 } 3786 } 3787 } 3788 *pt = ct; 3789 PetscFunctionReturn(0); 3790 } 3791 3792 /*@ 3793 DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 3794 3795 Collective on dm 3796 3797 Input Parameter: 3798 . mesh - The DMPlex 3799 3800 DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 3801 3802 Level: developer 3803 3804 Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 3805 internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 3806 automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 3807 3808 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel() 3809 @*/ 3810 PetscErrorCode DMPlexComputeCellTypes(DM dm) 3811 { 3812 DM_Plex *mesh; 3813 DMLabel ctLabel; 3814 PetscInt pStart, pEnd, p; 3815 PetscErrorCode ierr; 3816 3817 PetscFunctionBegin; 3818 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3819 mesh = (DM_Plex *) dm->data; 3820 ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr); 3821 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 3822 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3823 for (p = pStart; p < pEnd; ++p) { 3824 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3825 PetscInt pdepth; 3826 3827 ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr); 3828 ierr = DMPlexComputeCellType_Internal(dm, p, pdepth, &ct);CHKERRQ(ierr); 3829 if (ct == DM_POLYTOPE_UNKNOWN) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p); 3830 ierr = DMLabelSetValue(ctLabel, p, ct);CHKERRQ(ierr); 3831 } 3832 ierr = PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState);CHKERRQ(ierr); 3833 ierr = PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr); 3834 PetscFunctionReturn(0); 3835 } 3836 3837 /*@C 3838 DMPlexGetJoin - Get an array for the join of the set of points 3839 3840 Not Collective 3841 3842 Input Parameters: 3843 + dm - The DMPlex object 3844 . numPoints - The number of input points for the join 3845 - points - The input points 3846 3847 Output Parameters: 3848 + numCoveredPoints - The number of points in the join 3849 - coveredPoints - The points in the join 3850 3851 Level: intermediate 3852 3853 Note: Currently, this is restricted to a single level join 3854 3855 Fortran Notes: 3856 Since it returns an array, this routine is only available in Fortran 90, and you must 3857 include petsc.h90 in your code. 3858 3859 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3860 3861 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 3862 @*/ 3863 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3864 { 3865 DM_Plex *mesh = (DM_Plex*) dm->data; 3866 PetscInt *join[2]; 3867 PetscInt joinSize, i = 0; 3868 PetscInt dof, off, p, c, m; 3869 PetscErrorCode ierr; 3870 3871 PetscFunctionBegin; 3872 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3873 PetscValidIntPointer(points, 3); 3874 PetscValidIntPointer(numCoveredPoints, 4); 3875 PetscValidPointer(coveredPoints, 5); 3876 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 3877 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 3878 /* Copy in support of first point */ 3879 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 3880 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 3881 for (joinSize = 0; joinSize < dof; ++joinSize) { 3882 join[i][joinSize] = mesh->supports[off+joinSize]; 3883 } 3884 /* Check each successive support */ 3885 for (p = 1; p < numPoints; ++p) { 3886 PetscInt newJoinSize = 0; 3887 3888 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 3889 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 3890 for (c = 0; c < dof; ++c) { 3891 const PetscInt point = mesh->supports[off+c]; 3892 3893 for (m = 0; m < joinSize; ++m) { 3894 if (point == join[i][m]) { 3895 join[1-i][newJoinSize++] = point; 3896 break; 3897 } 3898 } 3899 } 3900 joinSize = newJoinSize; 3901 i = 1-i; 3902 } 3903 *numCoveredPoints = joinSize; 3904 *coveredPoints = join[i]; 3905 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 3906 PetscFunctionReturn(0); 3907 } 3908 3909 /*@C 3910 DMPlexRestoreJoin - Restore an array for the join of the set of points 3911 3912 Not Collective 3913 3914 Input Parameters: 3915 + dm - The DMPlex object 3916 . numPoints - The number of input points for the join 3917 - points - The input points 3918 3919 Output Parameters: 3920 + numCoveredPoints - The number of points in the join 3921 - coveredPoints - The points in the join 3922 3923 Fortran Notes: 3924 Since it returns an array, this routine is only available in Fortran 90, and you must 3925 include petsc.h90 in your code. 3926 3927 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3928 3929 Level: intermediate 3930 3931 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 3932 @*/ 3933 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3934 { 3935 PetscErrorCode ierr; 3936 3937 PetscFunctionBegin; 3938 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3939 if (points) PetscValidIntPointer(points,3); 3940 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 3941 PetscValidPointer(coveredPoints, 5); 3942 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 3943 if (numCoveredPoints) *numCoveredPoints = 0; 3944 PetscFunctionReturn(0); 3945 } 3946 3947 /*@C 3948 DMPlexGetFullJoin - Get an array for the join of the set of points 3949 3950 Not Collective 3951 3952 Input Parameters: 3953 + dm - The DMPlex object 3954 . numPoints - The number of input points for the join 3955 - points - The input points 3956 3957 Output Parameters: 3958 + numCoveredPoints - The number of points in the join 3959 - coveredPoints - The points in the join 3960 3961 Fortran Notes: 3962 Since it returns an array, this routine is only available in Fortran 90, and you must 3963 include petsc.h90 in your code. 3964 3965 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3966 3967 Level: intermediate 3968 3969 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 3970 @*/ 3971 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3972 { 3973 DM_Plex *mesh = (DM_Plex*) dm->data; 3974 PetscInt *offsets, **closures; 3975 PetscInt *join[2]; 3976 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 3977 PetscInt p, d, c, m, ms; 3978 PetscErrorCode ierr; 3979 3980 PetscFunctionBegin; 3981 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3982 PetscValidIntPointer(points, 3); 3983 PetscValidIntPointer(numCoveredPoints, 4); 3984 PetscValidPointer(coveredPoints, 5); 3985 3986 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3987 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 3988 ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 3989 ms = mesh->maxSupportSize; 3990 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 3991 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 3992 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 3993 3994 for (p = 0; p < numPoints; ++p) { 3995 PetscInt closureSize; 3996 3997 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 3998 3999 offsets[p*(depth+2)+0] = 0; 4000 for (d = 0; d < depth+1; ++d) { 4001 PetscInt pStart, pEnd, i; 4002 4003 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 4004 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4005 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4006 offsets[p*(depth+2)+d+1] = i; 4007 break; 4008 } 4009 } 4010 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4011 } 4012 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); 4013 } 4014 for (d = 0; d < depth+1; ++d) { 4015 PetscInt dof; 4016 4017 /* Copy in support of first point */ 4018 dof = offsets[d+1] - offsets[d]; 4019 for (joinSize = 0; joinSize < dof; ++joinSize) { 4020 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4021 } 4022 /* Check each successive cone */ 4023 for (p = 1; p < numPoints && joinSize; ++p) { 4024 PetscInt newJoinSize = 0; 4025 4026 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4027 for (c = 0; c < dof; ++c) { 4028 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4029 4030 for (m = 0; m < joinSize; ++m) { 4031 if (point == join[i][m]) { 4032 join[1-i][newJoinSize++] = point; 4033 break; 4034 } 4035 } 4036 } 4037 joinSize = newJoinSize; 4038 i = 1-i; 4039 } 4040 if (joinSize) break; 4041 } 4042 *numCoveredPoints = joinSize; 4043 *coveredPoints = join[i]; 4044 for (p = 0; p < numPoints; ++p) { 4045 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 4046 } 4047 ierr = PetscFree(closures);CHKERRQ(ierr); 4048 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4049 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4050 PetscFunctionReturn(0); 4051 } 4052 4053 /*@C 4054 DMPlexGetMeet - Get an array for the meet of the set of points 4055 4056 Not Collective 4057 4058 Input Parameters: 4059 + dm - The DMPlex object 4060 . numPoints - The number of input points for the meet 4061 - points - The input points 4062 4063 Output Parameters: 4064 + numCoveredPoints - The number of points in the meet 4065 - coveredPoints - The points in the meet 4066 4067 Level: intermediate 4068 4069 Note: Currently, this is restricted to a single level meet 4070 4071 Fortran Notes: 4072 Since it returns an array, this routine is only available in Fortran 90, and you must 4073 include petsc.h90 in your code. 4074 4075 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4076 4077 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 4078 @*/ 4079 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4080 { 4081 DM_Plex *mesh = (DM_Plex*) dm->data; 4082 PetscInt *meet[2]; 4083 PetscInt meetSize, i = 0; 4084 PetscInt dof, off, p, c, m; 4085 PetscErrorCode ierr; 4086 4087 PetscFunctionBegin; 4088 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4089 PetscValidPointer(points, 3); 4090 PetscValidPointer(numCoveringPoints, 4); 4091 PetscValidPointer(coveringPoints, 5); 4092 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4093 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4094 /* Copy in cone of first point */ 4095 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 4096 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 4097 for (meetSize = 0; meetSize < dof; ++meetSize) { 4098 meet[i][meetSize] = mesh->cones[off+meetSize]; 4099 } 4100 /* Check each successive cone */ 4101 for (p = 1; p < numPoints; ++p) { 4102 PetscInt newMeetSize = 0; 4103 4104 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 4105 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 4106 for (c = 0; c < dof; ++c) { 4107 const PetscInt point = mesh->cones[off+c]; 4108 4109 for (m = 0; m < meetSize; ++m) { 4110 if (point == meet[i][m]) { 4111 meet[1-i][newMeetSize++] = point; 4112 break; 4113 } 4114 } 4115 } 4116 meetSize = newMeetSize; 4117 i = 1-i; 4118 } 4119 *numCoveringPoints = meetSize; 4120 *coveringPoints = meet[i]; 4121 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4122 PetscFunctionReturn(0); 4123 } 4124 4125 /*@C 4126 DMPlexRestoreMeet - Restore an array for the meet of the set of points 4127 4128 Not Collective 4129 4130 Input Parameters: 4131 + dm - The DMPlex object 4132 . numPoints - The number of input points for the meet 4133 - points - The input points 4134 4135 Output Parameters: 4136 + numCoveredPoints - The number of points in the meet 4137 - coveredPoints - The points in the meet 4138 4139 Level: intermediate 4140 4141 Fortran Notes: 4142 Since it returns an array, this routine is only available in Fortran 90, and you must 4143 include petsc.h90 in your code. 4144 4145 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4146 4147 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 4148 @*/ 4149 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4150 { 4151 PetscErrorCode ierr; 4152 4153 PetscFunctionBegin; 4154 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4155 if (points) PetscValidIntPointer(points,3); 4156 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4157 PetscValidPointer(coveredPoints,5); 4158 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4159 if (numCoveredPoints) *numCoveredPoints = 0; 4160 PetscFunctionReturn(0); 4161 } 4162 4163 /*@C 4164 DMPlexGetFullMeet - Get an array for the meet of the set of points 4165 4166 Not Collective 4167 4168 Input Parameters: 4169 + dm - The DMPlex object 4170 . numPoints - The number of input points for the meet 4171 - points - The input points 4172 4173 Output Parameters: 4174 + numCoveredPoints - The number of points in the meet 4175 - coveredPoints - The points in the meet 4176 4177 Level: intermediate 4178 4179 Fortran Notes: 4180 Since it returns an array, this routine is only available in Fortran 90, and you must 4181 include petsc.h90 in your code. 4182 4183 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4184 4185 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 4186 @*/ 4187 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4188 { 4189 DM_Plex *mesh = (DM_Plex*) dm->data; 4190 PetscInt *offsets, **closures; 4191 PetscInt *meet[2]; 4192 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 4193 PetscInt p, h, c, m, mc; 4194 PetscErrorCode ierr; 4195 4196 PetscFunctionBegin; 4197 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4198 PetscValidPointer(points, 3); 4199 PetscValidPointer(numCoveredPoints, 4); 4200 PetscValidPointer(coveredPoints, 5); 4201 4202 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 4203 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 4204 ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4205 mc = mesh->maxConeSize; 4206 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 4207 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4208 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4209 4210 for (p = 0; p < numPoints; ++p) { 4211 PetscInt closureSize; 4212 4213 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 4214 4215 offsets[p*(height+2)+0] = 0; 4216 for (h = 0; h < height+1; ++h) { 4217 PetscInt pStart, pEnd, i; 4218 4219 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 4220 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4221 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4222 offsets[p*(height+2)+h+1] = i; 4223 break; 4224 } 4225 } 4226 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4227 } 4228 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); 4229 } 4230 for (h = 0; h < height+1; ++h) { 4231 PetscInt dof; 4232 4233 /* Copy in cone of first point */ 4234 dof = offsets[h+1] - offsets[h]; 4235 for (meetSize = 0; meetSize < dof; ++meetSize) { 4236 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4237 } 4238 /* Check each successive cone */ 4239 for (p = 1; p < numPoints && meetSize; ++p) { 4240 PetscInt newMeetSize = 0; 4241 4242 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4243 for (c = 0; c < dof; ++c) { 4244 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4245 4246 for (m = 0; m < meetSize; ++m) { 4247 if (point == meet[i][m]) { 4248 meet[1-i][newMeetSize++] = point; 4249 break; 4250 } 4251 } 4252 } 4253 meetSize = newMeetSize; 4254 i = 1-i; 4255 } 4256 if (meetSize) break; 4257 } 4258 *numCoveredPoints = meetSize; 4259 *coveredPoints = meet[i]; 4260 for (p = 0; p < numPoints; ++p) { 4261 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 4262 } 4263 ierr = PetscFree(closures);CHKERRQ(ierr); 4264 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4265 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4266 PetscFunctionReturn(0); 4267 } 4268 4269 /*@C 4270 DMPlexEqual - Determine if two DMs have the same topology 4271 4272 Not Collective 4273 4274 Input Parameters: 4275 + dmA - A DMPlex object 4276 - dmB - A DMPlex object 4277 4278 Output Parameters: 4279 . equal - PETSC_TRUE if the topologies are identical 4280 4281 Level: intermediate 4282 4283 Notes: 4284 We are not solving graph isomorphism, so we do not permutation. 4285 4286 .seealso: DMPlexGetCone() 4287 @*/ 4288 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 4289 { 4290 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 4291 PetscErrorCode ierr; 4292 4293 PetscFunctionBegin; 4294 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 4295 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4296 PetscValidPointer(equal, 3); 4297 4298 *equal = PETSC_FALSE; 4299 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 4300 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 4301 if (depth != depthB) PetscFunctionReturn(0); 4302 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 4303 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 4304 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 4305 for (p = pStart; p < pEnd; ++p) { 4306 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 4307 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 4308 4309 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 4310 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 4311 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 4312 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 4313 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 4314 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 4315 if (coneSize != coneSizeB) PetscFunctionReturn(0); 4316 for (c = 0; c < coneSize; ++c) { 4317 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 4318 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 4319 } 4320 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 4321 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 4322 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 4323 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 4324 if (supportSize != supportSizeB) PetscFunctionReturn(0); 4325 for (s = 0; s < supportSize; ++s) { 4326 if (support[s] != supportB[s]) PetscFunctionReturn(0); 4327 } 4328 } 4329 *equal = PETSC_TRUE; 4330 PetscFunctionReturn(0); 4331 } 4332 4333 /*@C 4334 DMPlexGetNumFaceVertices - Returns the number of vertices on a face 4335 4336 Not Collective 4337 4338 Input Parameters: 4339 + dm - The DMPlex 4340 . cellDim - The cell dimension 4341 - numCorners - The number of vertices on a cell 4342 4343 Output Parameters: 4344 . numFaceVertices - The number of vertices on a face 4345 4346 Level: developer 4347 4348 Notes: 4349 Of course this can only work for a restricted set of symmetric shapes 4350 4351 .seealso: DMPlexGetCone() 4352 @*/ 4353 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4354 { 4355 MPI_Comm comm; 4356 PetscErrorCode ierr; 4357 4358 PetscFunctionBegin; 4359 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4360 PetscValidPointer(numFaceVertices,4); 4361 switch (cellDim) { 4362 case 0: 4363 *numFaceVertices = 0; 4364 break; 4365 case 1: 4366 *numFaceVertices = 1; 4367 break; 4368 case 2: 4369 switch (numCorners) { 4370 case 3: /* triangle */ 4371 *numFaceVertices = 2; /* Edge has 2 vertices */ 4372 break; 4373 case 4: /* quadrilateral */ 4374 *numFaceVertices = 2; /* Edge has 2 vertices */ 4375 break; 4376 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 4377 *numFaceVertices = 3; /* Edge has 3 vertices */ 4378 break; 4379 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 4380 *numFaceVertices = 3; /* Edge has 3 vertices */ 4381 break; 4382 default: 4383 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4384 } 4385 break; 4386 case 3: 4387 switch (numCorners) { 4388 case 4: /* tetradehdron */ 4389 *numFaceVertices = 3; /* Face has 3 vertices */ 4390 break; 4391 case 6: /* tet cohesive cells */ 4392 *numFaceVertices = 4; /* Face has 4 vertices */ 4393 break; 4394 case 8: /* hexahedron */ 4395 *numFaceVertices = 4; /* Face has 4 vertices */ 4396 break; 4397 case 9: /* tet cohesive Lagrange cells */ 4398 *numFaceVertices = 6; /* Face has 6 vertices */ 4399 break; 4400 case 10: /* quadratic tetrahedron */ 4401 *numFaceVertices = 6; /* Face has 6 vertices */ 4402 break; 4403 case 12: /* hex cohesive Lagrange cells */ 4404 *numFaceVertices = 6; /* Face has 6 vertices */ 4405 break; 4406 case 18: /* quadratic tet cohesive Lagrange cells */ 4407 *numFaceVertices = 6; /* Face has 6 vertices */ 4408 break; 4409 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 4410 *numFaceVertices = 9; /* Face has 9 vertices */ 4411 break; 4412 default: 4413 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4414 } 4415 break; 4416 default: 4417 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 4418 } 4419 PetscFunctionReturn(0); 4420 } 4421 4422 /*@ 4423 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4424 4425 Not Collective 4426 4427 Input Parameter: 4428 . dm - The DMPlex object 4429 4430 Output Parameter: 4431 . depthLabel - The DMLabel recording point depth 4432 4433 Level: developer 4434 4435 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), 4436 @*/ 4437 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4438 { 4439 PetscFunctionBegin; 4440 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4441 PetscValidPointer(depthLabel, 2); 4442 *depthLabel = dm->depthLabel; 4443 PetscFunctionReturn(0); 4444 } 4445 4446 /*@ 4447 DMPlexGetDepth - Get the depth of the DAG representing this mesh 4448 4449 Not Collective 4450 4451 Input Parameter: 4452 . dm - The DMPlex object 4453 4454 Output Parameter: 4455 . depth - The number of strata (breadth first levels) in the DAG 4456 4457 Level: developer 4458 4459 Notes: 4460 This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4461 The point depth is described more in detail in DMPlexGetDepthStratum(). 4462 An empty mesh gives -1. 4463 4464 .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize() 4465 @*/ 4466 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4467 { 4468 DMLabel label; 4469 PetscInt d = 0; 4470 PetscErrorCode ierr; 4471 4472 PetscFunctionBegin; 4473 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4474 PetscValidPointer(depth, 2); 4475 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4476 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 4477 *depth = d-1; 4478 PetscFunctionReturn(0); 4479 } 4480 4481 /*@ 4482 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4483 4484 Not Collective 4485 4486 Input Parameters: 4487 + dm - The DMPlex object 4488 - stratumValue - The requested depth 4489 4490 Output Parameters: 4491 + start - The first point at this depth 4492 - end - One beyond the last point at this depth 4493 4494 Notes: 4495 Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4496 often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4497 higher dimension, e.g., "edges". 4498 4499 Level: developer 4500 4501 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate() 4502 @*/ 4503 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4504 { 4505 DMLabel label; 4506 PetscInt pStart, pEnd; 4507 PetscErrorCode ierr; 4508 4509 PetscFunctionBegin; 4510 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4511 if (start) {PetscValidPointer(start, 3); *start = 0;} 4512 if (end) {PetscValidPointer(end, 4); *end = 0;} 4513 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4514 if (pStart == pEnd) PetscFunctionReturn(0); 4515 if (stratumValue < 0) { 4516 if (start) *start = pStart; 4517 if (end) *end = pEnd; 4518 PetscFunctionReturn(0); 4519 } 4520 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4521 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4522 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 4523 PetscFunctionReturn(0); 4524 } 4525 4526 /*@ 4527 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4528 4529 Not Collective 4530 4531 Input Parameters: 4532 + dm - The DMPlex object 4533 - stratumValue - The requested height 4534 4535 Output Parameters: 4536 + start - The first point at this height 4537 - end - One beyond the last point at this height 4538 4539 Notes: 4540 Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4541 points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4542 stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4543 4544 Level: developer 4545 4546 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight() 4547 @*/ 4548 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4549 { 4550 DMLabel label; 4551 PetscInt depth, pStart, pEnd; 4552 PetscErrorCode ierr; 4553 4554 PetscFunctionBegin; 4555 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4556 if (start) {PetscValidPointer(start, 3); *start = 0;} 4557 if (end) {PetscValidPointer(end, 4); *end = 0;} 4558 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4559 if (pStart == pEnd) PetscFunctionReturn(0); 4560 if (stratumValue < 0) { 4561 if (start) *start = pStart; 4562 if (end) *end = pEnd; 4563 PetscFunctionReturn(0); 4564 } 4565 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4566 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4567 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 4568 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 4569 PetscFunctionReturn(0); 4570 } 4571 4572 /*@ 4573 DMPlexGetPointDepth - Get the depth of a given point 4574 4575 Not Collective 4576 4577 Input Parameter: 4578 + dm - The DMPlex object 4579 - point - The point 4580 4581 Output Parameter: 4582 . depth - The depth of the point 4583 4584 Level: intermediate 4585 4586 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight() 4587 @*/ 4588 PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4589 { 4590 PetscErrorCode ierr; 4591 4592 PetscFunctionBegin; 4593 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4594 PetscValidIntPointer(depth, 3); 4595 ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr); 4596 PetscFunctionReturn(0); 4597 } 4598 4599 /*@ 4600 DMPlexGetPointHeight - Get the height of a given point 4601 4602 Not Collective 4603 4604 Input Parameter: 4605 + dm - The DMPlex object 4606 - point - The point 4607 4608 Output Parameter: 4609 . height - The height of the point 4610 4611 Level: intermediate 4612 4613 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth() 4614 @*/ 4615 PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 4616 { 4617 PetscInt n, pDepth; 4618 PetscErrorCode ierr; 4619 4620 PetscFunctionBegin; 4621 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4622 PetscValidIntPointer(height, 3); 4623 ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr); 4624 ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr); 4625 *height = n - 1 - pDepth; /* DAG depth is n-1 */ 4626 PetscFunctionReturn(0); 4627 } 4628 4629 /*@ 4630 DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4631 4632 Not Collective 4633 4634 Input Parameter: 4635 . dm - The DMPlex object 4636 4637 Output Parameter: 4638 . celltypeLabel - The DMLabel recording cell polytope type 4639 4640 Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4641 DMCreateLabel(dm, "celltype") beforehand. 4642 4643 Level: developer 4644 4645 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel() 4646 @*/ 4647 PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4648 { 4649 PetscErrorCode ierr; 4650 4651 PetscFunctionBegin; 4652 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4653 PetscValidPointer(celltypeLabel, 2); 4654 if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);} 4655 *celltypeLabel = dm->celltypeLabel; 4656 PetscFunctionReturn(0); 4657 } 4658 4659 /*@ 4660 DMPlexGetCellType - Get the polytope type of a given cell 4661 4662 Not Collective 4663 4664 Input Parameter: 4665 + dm - The DMPlex object 4666 - cell - The cell 4667 4668 Output Parameter: 4669 . celltype - The polytope type of the cell 4670 4671 Level: intermediate 4672 4673 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth() 4674 @*/ 4675 PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4676 { 4677 DMLabel label; 4678 PetscInt ct; 4679 PetscErrorCode ierr; 4680 4681 PetscFunctionBegin; 4682 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4683 PetscValidPointer(celltype, 3); 4684 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4685 ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr); 4686 if (ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell); 4687 *celltype = (DMPolytopeType) ct; 4688 PetscFunctionReturn(0); 4689 } 4690 4691 /*@ 4692 DMPlexSetCellType - Set the polytope type of a given cell 4693 4694 Not Collective 4695 4696 Input Parameters: 4697 + dm - The DMPlex object 4698 . cell - The cell 4699 - celltype - The polytope type of the cell 4700 4701 Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 4702 is executed. This function will override the computed type. However, if automatic classification will not succeed 4703 and a user wants to manually specify all types, the classification must be disabled by calling 4704 DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 4705 4706 Level: advanced 4707 4708 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel() 4709 @*/ 4710 PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 4711 { 4712 DMLabel label; 4713 PetscErrorCode ierr; 4714 4715 PetscFunctionBegin; 4716 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4717 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4718 ierr = DMLabelSetValue(label, cell, celltype);CHKERRQ(ierr); 4719 PetscFunctionReturn(0); 4720 } 4721 4722 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 4723 { 4724 PetscSection section, s; 4725 Mat m; 4726 PetscInt maxHeight; 4727 PetscErrorCode ierr; 4728 4729 PetscFunctionBegin; 4730 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 4731 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 4732 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 4733 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 4734 ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr); 4735 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 4736 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 4737 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 4738 ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr); 4739 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 4740 ierr = MatDestroy(&m);CHKERRQ(ierr); 4741 4742 ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr); 4743 ierr = DMCreateDS(*cdm);CHKERRQ(ierr); 4744 PetscFunctionReturn(0); 4745 } 4746 4747 PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 4748 { 4749 Vec coordsLocal; 4750 DM coordsDM; 4751 PetscErrorCode ierr; 4752 4753 PetscFunctionBegin; 4754 *field = NULL; 4755 ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr); 4756 ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr); 4757 if (coordsLocal && coordsDM) { 4758 ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr); 4759 } 4760 PetscFunctionReturn(0); 4761 } 4762 4763 /*@C 4764 DMPlexGetConeSection - Return a section which describes the layout of cone data 4765 4766 Not Collective 4767 4768 Input Parameters: 4769 . dm - The DMPlex object 4770 4771 Output Parameter: 4772 . section - The PetscSection object 4773 4774 Level: developer 4775 4776 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 4777 @*/ 4778 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 4779 { 4780 DM_Plex *mesh = (DM_Plex*) dm->data; 4781 4782 PetscFunctionBegin; 4783 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4784 if (section) *section = mesh->coneSection; 4785 PetscFunctionReturn(0); 4786 } 4787 4788 /*@C 4789 DMPlexGetSupportSection - Return a section which describes the layout of support data 4790 4791 Not Collective 4792 4793 Input Parameters: 4794 . dm - The DMPlex object 4795 4796 Output Parameter: 4797 . section - The PetscSection object 4798 4799 Level: developer 4800 4801 .seealso: DMPlexGetConeSection() 4802 @*/ 4803 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 4804 { 4805 DM_Plex *mesh = (DM_Plex*) dm->data; 4806 4807 PetscFunctionBegin; 4808 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4809 if (section) *section = mesh->supportSection; 4810 PetscFunctionReturn(0); 4811 } 4812 4813 /*@C 4814 DMPlexGetCones - Return cone data 4815 4816 Not Collective 4817 4818 Input Parameters: 4819 . dm - The DMPlex object 4820 4821 Output Parameter: 4822 . cones - The cone for each point 4823 4824 Level: developer 4825 4826 .seealso: DMPlexGetConeSection() 4827 @*/ 4828 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 4829 { 4830 DM_Plex *mesh = (DM_Plex*) dm->data; 4831 4832 PetscFunctionBegin; 4833 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4834 if (cones) *cones = mesh->cones; 4835 PetscFunctionReturn(0); 4836 } 4837 4838 /*@C 4839 DMPlexGetConeOrientations - Return cone orientation data 4840 4841 Not Collective 4842 4843 Input Parameters: 4844 . dm - The DMPlex object 4845 4846 Output Parameter: 4847 . coneOrientations - The cone orientation for each point 4848 4849 Level: developer 4850 4851 .seealso: DMPlexGetConeSection() 4852 @*/ 4853 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 4854 { 4855 DM_Plex *mesh = (DM_Plex*) dm->data; 4856 4857 PetscFunctionBegin; 4858 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4859 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 4860 PetscFunctionReturn(0); 4861 } 4862 4863 /******************************** FEM Support **********************************/ 4864 4865 /* 4866 Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 4867 representing a line in the section. 4868 */ 4869 static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 4870 { 4871 PetscErrorCode ierr; 4872 4873 PetscFunctionBeginHot; 4874 ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr); 4875 if (line < 0) { 4876 *k = 0; 4877 *Nc = 0; 4878 } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 4879 *k = 1; 4880 } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 4881 /* An order k SEM disc has k-1 dofs on an edge */ 4882 ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr); 4883 *k = *k / *Nc + 1; 4884 } 4885 PetscFunctionReturn(0); 4886 } 4887 4888 /*@ 4889 4890 DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 4891 lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 4892 section provided (or the section of the DM). 4893 4894 Input Parameters: 4895 + dm - The DM 4896 . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 4897 - section - The PetscSection to reorder, or NULL for the default section 4898 4899 Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 4900 degree of the basis. 4901 4902 Example: 4903 A typical interpolated single-quad mesh might order points as 4904 .vb 4905 [c0, v1, v2, v3, v4, e5, e6, e7, e8] 4906 4907 v4 -- e6 -- v3 4908 | | 4909 e7 c0 e8 4910 | | 4911 v1 -- e5 -- v2 4912 .ve 4913 4914 (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 4915 dofs in the order of points, e.g., 4916 .vb 4917 c0 -> [0,1,2,3] 4918 v1 -> [4] 4919 ... 4920 e5 -> [8, 9] 4921 .ve 4922 4923 which corresponds to the dofs 4924 .vb 4925 6 10 11 7 4926 13 2 3 15 4927 12 0 1 14 4928 4 8 9 5 4929 .ve 4930 4931 The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 4932 .vb 4933 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 4934 .ve 4935 4936 After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 4937 .vb 4938 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 4939 .ve 4940 4941 Level: developer 4942 4943 .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection() 4944 @*/ 4945 PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 4946 { 4947 DMLabel label; 4948 PetscInt dim, depth = -1, eStart = -1, Nf; 4949 PetscBool vertexchart; 4950 PetscErrorCode ierr; 4951 4952 PetscFunctionBegin; 4953 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4954 if (dim < 1) PetscFunctionReturn(0); 4955 if (point < 0) { 4956 PetscInt sStart,sEnd; 4957 4958 ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr); 4959 point = sEnd-sStart ? sStart : point; 4960 } 4961 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4962 if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); } 4963 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 4964 if (depth == 1) {eStart = point;} 4965 else if (depth == dim) { 4966 const PetscInt *cone; 4967 4968 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4969 if (dim == 2) eStart = cone[0]; 4970 else if (dim == 3) { 4971 const PetscInt *cone2; 4972 ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 4973 eStart = cone2[0]; 4974 } 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); 4975 } 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); 4976 { /* Determine whether the chart covers all points or just vertices. */ 4977 PetscInt pStart,pEnd,cStart,cEnd; 4978 ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr); 4979 ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr); 4980 if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Just vertices */ 4981 else vertexchart = PETSC_FALSE; /* Assume all interpolated points are in chart */ 4982 } 4983 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 4984 for (PetscInt d=1; d<=dim; d++) { 4985 PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 4986 PetscInt *perm; 4987 4988 for (f = 0; f < Nf; ++f) { 4989 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 4990 size += PetscPowInt(k+1, d)*Nc; 4991 } 4992 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 4993 for (f = 0; f < Nf; ++f) { 4994 switch (d) { 4995 case 1: 4996 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 4997 /* 4998 Original ordering is [ edge of length k-1; vtx0; vtx1 ] 4999 We want [ vtx0; edge of length k-1; vtx1 ] 5000 */ 5001 for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5002 for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5003 for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5004 foffset = offset; 5005 break; 5006 case 2: 5007 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 5008 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5009 /* The SEM order is 5010 5011 v_lb, {e_b}, v_rb, 5012 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 5013 v_lt, reverse {e_t}, v_rt 5014 */ 5015 { 5016 const PetscInt of = 0; 5017 const PetscInt oeb = of + PetscSqr(k-1); 5018 const PetscInt oer = oeb + (k-1); 5019 const PetscInt oet = oer + (k-1); 5020 const PetscInt oel = oet + (k-1); 5021 const PetscInt ovlb = oel + (k-1); 5022 const PetscInt ovrb = ovlb + 1; 5023 const PetscInt ovrt = ovrb + 1; 5024 const PetscInt ovlt = ovrt + 1; 5025 PetscInt o; 5026 5027 /* bottom */ 5028 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 5029 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5030 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 5031 /* middle */ 5032 for (i = 0; i < k-1; ++i) { 5033 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 5034 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; 5035 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 5036 } 5037 /* top */ 5038 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 5039 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5040 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 5041 foffset = offset; 5042 } 5043 break; 5044 case 3: 5045 /* The original hex closure is 5046 5047 {c, 5048 f_b, f_t, f_f, f_b, f_r, f_l, 5049 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 5050 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 5051 */ 5052 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5053 /* The SEM order is 5054 Bottom Slice 5055 v_blf, {e^{(k-1)-n}_bf}, v_brf, 5056 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 5057 v_blb, {e_bb}, v_brb, 5058 5059 Middle Slice (j) 5060 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 5061 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 5062 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 5063 5064 Top Slice 5065 v_tlf, {e_tf}, v_trf, 5066 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 5067 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 5068 */ 5069 { 5070 const PetscInt oc = 0; 5071 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 5072 const PetscInt oft = ofb + PetscSqr(k-1); 5073 const PetscInt off = oft + PetscSqr(k-1); 5074 const PetscInt ofk = off + PetscSqr(k-1); 5075 const PetscInt ofr = ofk + PetscSqr(k-1); 5076 const PetscInt ofl = ofr + PetscSqr(k-1); 5077 const PetscInt oebl = ofl + PetscSqr(k-1); 5078 const PetscInt oebb = oebl + (k-1); 5079 const PetscInt oebr = oebb + (k-1); 5080 const PetscInt oebf = oebr + (k-1); 5081 const PetscInt oetf = oebf + (k-1); 5082 const PetscInt oetr = oetf + (k-1); 5083 const PetscInt oetb = oetr + (k-1); 5084 const PetscInt oetl = oetb + (k-1); 5085 const PetscInt oerf = oetl + (k-1); 5086 const PetscInt oelf = oerf + (k-1); 5087 const PetscInt oelb = oelf + (k-1); 5088 const PetscInt oerb = oelb + (k-1); 5089 const PetscInt ovblf = oerb + (k-1); 5090 const PetscInt ovblb = ovblf + 1; 5091 const PetscInt ovbrb = ovblb + 1; 5092 const PetscInt ovbrf = ovbrb + 1; 5093 const PetscInt ovtlf = ovbrf + 1; 5094 const PetscInt ovtrf = ovtlf + 1; 5095 const PetscInt ovtrb = ovtrf + 1; 5096 const PetscInt ovtlb = ovtrb + 1; 5097 PetscInt o, n; 5098 5099 /* Bottom Slice */ 5100 /* bottom */ 5101 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 5102 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5103 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 5104 /* middle */ 5105 for (i = 0; i < k-1; ++i) { 5106 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5107 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;} 5108 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 5109 } 5110 /* top */ 5111 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 5112 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5113 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 5114 5115 /* Middle Slice */ 5116 for (j = 0; j < k-1; ++j) { 5117 /* bottom */ 5118 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 5119 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; 5120 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 5121 /* middle */ 5122 for (i = 0; i < k-1; ++i) { 5123 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 5124 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; 5125 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 5126 } 5127 /* top */ 5128 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 5129 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; 5130 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 5131 } 5132 5133 /* Top Slice */ 5134 /* bottom */ 5135 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 5136 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5137 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 5138 /* middle */ 5139 for (i = 0; i < k-1; ++i) { 5140 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 5141 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 5142 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 5143 } 5144 /* top */ 5145 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 5146 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5147 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 5148 5149 foffset = offset; 5150 } 5151 break; 5152 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d); 5153 } 5154 } 5155 if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 5156 /* Check permutation */ 5157 { 5158 PetscInt *check; 5159 5160 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 5161 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]);} 5162 for (i = 0; i < size; ++i) check[perm[i]] = i; 5163 for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 5164 ierr = PetscFree(check);CHKERRQ(ierr); 5165 } 5166 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 5167 } 5168 PetscFunctionReturn(0); 5169 } 5170 5171 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5172 { 5173 PetscDS prob; 5174 PetscInt depth, Nf, h; 5175 DMLabel label; 5176 PetscErrorCode ierr; 5177 5178 PetscFunctionBeginHot; 5179 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 5180 Nf = prob->Nf; 5181 label = dm->depthLabel; 5182 *dspace = NULL; 5183 if (field < Nf) { 5184 PetscObject disc = prob->disc[field]; 5185 5186 if (disc->classid == PETSCFE_CLASSID) { 5187 PetscDualSpace dsp; 5188 5189 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 5190 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 5191 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 5192 h = depth - 1 - h; 5193 if (h) { 5194 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 5195 } else { 5196 *dspace = dsp; 5197 } 5198 } 5199 } 5200 PetscFunctionReturn(0); 5201 } 5202 5203 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5204 { 5205 PetscScalar *array, *vArray; 5206 const PetscInt *cone, *coneO; 5207 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5208 PetscErrorCode ierr; 5209 5210 PetscFunctionBeginHot; 5211 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5212 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5213 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5214 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5215 if (!values || !*values) { 5216 if ((point >= pStart) && (point < pEnd)) { 5217 PetscInt dof; 5218 5219 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5220 size += dof; 5221 } 5222 for (p = 0; p < numPoints; ++p) { 5223 const PetscInt cp = cone[p]; 5224 PetscInt dof; 5225 5226 if ((cp < pStart) || (cp >= pEnd)) continue; 5227 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5228 size += dof; 5229 } 5230 if (!values) { 5231 if (csize) *csize = size; 5232 PetscFunctionReturn(0); 5233 } 5234 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 5235 } else { 5236 array = *values; 5237 } 5238 size = 0; 5239 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 5240 if ((point >= pStart) && (point < pEnd)) { 5241 PetscInt dof, off, d; 5242 PetscScalar *varr; 5243 5244 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5245 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5246 varr = &vArray[off]; 5247 for (d = 0; d < dof; ++d, ++offset) { 5248 array[offset] = varr[d]; 5249 } 5250 size += dof; 5251 } 5252 for (p = 0; p < numPoints; ++p) { 5253 const PetscInt cp = cone[p]; 5254 PetscInt o = coneO[p]; 5255 PetscInt dof, off, d; 5256 PetscScalar *varr; 5257 5258 if ((cp < pStart) || (cp >= pEnd)) continue; 5259 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5260 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 5261 varr = &vArray[off]; 5262 if (o >= 0) { 5263 for (d = 0; d < dof; ++d, ++offset) { 5264 array[offset] = varr[d]; 5265 } 5266 } else { 5267 for (d = dof-1; d >= 0; --d, ++offset) { 5268 array[offset] = varr[d]; 5269 } 5270 } 5271 size += dof; 5272 } 5273 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 5274 if (!*values) { 5275 if (csize) *csize = size; 5276 *values = array; 5277 } else { 5278 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5279 *csize = size; 5280 } 5281 PetscFunctionReturn(0); 5282 } 5283 5284 /* Compress out points not in the section */ 5285 PETSC_STATIC_INLINE PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 5286 { 5287 const PetscInt np = *numPoints; 5288 PetscInt pStart, pEnd, p, q; 5289 PetscErrorCode ierr; 5290 5291 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5292 for (p = 0, q = 0; p < np; ++p) { 5293 const PetscInt r = points[p*2]; 5294 if ((r >= pStart) && (r < pEnd)) { 5295 points[q*2] = r; 5296 points[q*2+1] = points[p*2+1]; 5297 ++q; 5298 } 5299 } 5300 *numPoints = q; 5301 return 0; 5302 } 5303 5304 static PetscErrorCode DMPlexTransitiveClosure_Hybrid_Internal(DM dm, PetscInt point, PetscInt np, PetscInt *numPoints, PetscInt **points) 5305 { 5306 const PetscInt *cone, *ornt; 5307 PetscInt *pts, *closure = NULL; 5308 PetscInt dim, coneSize, c, d, clSize, cl; 5309 PetscErrorCode ierr; 5310 5311 PetscFunctionBeginHot; 5312 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5313 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 5314 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5315 ierr = DMPlexGetConeOrientation(dm, point, &ornt);CHKERRQ(ierr); 5316 ierr = DMPlexGetTransitiveClosure(dm, cone[0], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 5317 ierr = DMGetWorkArray(dm, np*2, MPIU_INT, &pts);CHKERRQ(ierr); 5318 c = 0; 5319 pts[c*2+0] = point; 5320 pts[c*2+1] = 0; 5321 ++c; 5322 for (cl = 0; cl < clSize*2; cl += 2, ++c) {pts[c*2+0] = closure[cl]; pts[c*2+1] = closure[cl+1];} 5323 ierr = DMPlexGetTransitiveClosure(dm, cone[1], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 5324 for (cl = 0; cl < clSize*2; cl += 2, ++c) {pts[c*2+0] = closure[cl]; pts[c*2+1] = closure[cl+1];} 5325 ierr = DMPlexRestoreTransitiveClosure(dm, cone[0], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 5326 if (dim >= 2) { 5327 for (d = 2; d < coneSize; ++d, ++c) {pts[c*2+0] = cone[d]; pts[c*2+1] = ornt[d];} 5328 } 5329 if (dim >= 3) { 5330 for (d = 2; d < coneSize; ++d) { 5331 const PetscInt fpoint = cone[d]; 5332 const PetscInt *fcone; 5333 PetscInt fconeSize, fc, i; 5334 5335 ierr = DMPlexGetConeSize(dm, fpoint, &fconeSize);CHKERRQ(ierr); 5336 ierr = DMPlexGetCone(dm, fpoint, &fcone);CHKERRQ(ierr); 5337 for (fc = 0; fc < fconeSize; ++fc) { 5338 for (i = 0; i < c; ++i) if (pts[i*2] == fcone[fc]) break; 5339 if (i == c) {pts[c*2+0] = fcone[fc]; pts[c*2+1] = 0; ++c;} 5340 } 5341 } 5342 } 5343 if (c != np) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid closure for hybrid point %D, size %D != %D", point, c, np); 5344 *numPoints = np; 5345 *points = pts; 5346 PetscFunctionReturn(0); 5347 } 5348 5349 /* Compressed closure does not apply closure permutation */ 5350 PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5351 { 5352 const PetscInt *cla = NULL; 5353 PetscInt np, *pts = NULL; 5354 PetscErrorCode ierr; 5355 5356 PetscFunctionBeginHot; 5357 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 5358 if (*clPoints) { 5359 PetscInt dof, off; 5360 5361 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 5362 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 5363 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 5364 np = dof/2; 5365 pts = (PetscInt *) &cla[off]; 5366 } else { 5367 DMPolytopeType ct; 5368 5369 /* Do not make the label if it does not exist */ 5370 if (!dm->celltypeLabel) {ct = DM_POLYTOPE_POINT;} 5371 else {ierr = DMPlexGetCellType(dm, point, &ct);CHKERRQ(ierr);} 5372 switch (ct) { 5373 case DM_POLYTOPE_SEG_PRISM_TENSOR: 5374 ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 9, &np, &pts);CHKERRQ(ierr); 5375 break; 5376 case DM_POLYTOPE_TRI_PRISM_TENSOR: 5377 ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 21, &np, &pts);CHKERRQ(ierr); 5378 break; 5379 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 5380 ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 27, &np, &pts);CHKERRQ(ierr); 5381 break; 5382 default: 5383 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 5384 } 5385 ierr = CompressPoints_Private(section, &np, pts);CHKERRQ(ierr); 5386 } 5387 *numPoints = np; 5388 *points = pts; 5389 *clp = cla; 5390 PetscFunctionReturn(0); 5391 } 5392 5393 PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5394 { 5395 PetscErrorCode ierr; 5396 5397 PetscFunctionBeginHot; 5398 if (!*clPoints) { 5399 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 5400 } else { 5401 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 5402 } 5403 *numPoints = 0; 5404 *points = NULL; 5405 *clSec = NULL; 5406 *clPoints = NULL; 5407 *clp = NULL; 5408 PetscFunctionReturn(0); 5409 } 5410 5411 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[]) 5412 { 5413 PetscInt offset = 0, p; 5414 const PetscInt **perms = NULL; 5415 const PetscScalar **flips = NULL; 5416 PetscErrorCode ierr; 5417 5418 PetscFunctionBeginHot; 5419 *size = 0; 5420 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5421 for (p = 0; p < numPoints; p++) { 5422 const PetscInt point = points[2*p]; 5423 const PetscInt *perm = perms ? perms[p] : NULL; 5424 const PetscScalar *flip = flips ? flips[p] : NULL; 5425 PetscInt dof, off, d; 5426 const PetscScalar *varr; 5427 5428 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5429 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5430 varr = &vArray[off]; 5431 if (clperm) { 5432 if (perm) { 5433 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 5434 } else { 5435 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 5436 } 5437 if (flip) { 5438 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 5439 } 5440 } else { 5441 if (perm) { 5442 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 5443 } else { 5444 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 5445 } 5446 if (flip) { 5447 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 5448 } 5449 } 5450 offset += dof; 5451 } 5452 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5453 *size = offset; 5454 PetscFunctionReturn(0); 5455 } 5456 5457 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[]) 5458 { 5459 PetscInt offset = 0, f; 5460 PetscErrorCode ierr; 5461 5462 PetscFunctionBeginHot; 5463 *size = 0; 5464 for (f = 0; f < numFields; ++f) { 5465 PetscInt p; 5466 const PetscInt **perms = NULL; 5467 const PetscScalar **flips = NULL; 5468 5469 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5470 for (p = 0; p < numPoints; p++) { 5471 const PetscInt point = points[2*p]; 5472 PetscInt fdof, foff, b; 5473 const PetscScalar *varr; 5474 const PetscInt *perm = perms ? perms[p] : NULL; 5475 const PetscScalar *flip = flips ? flips[p] : NULL; 5476 5477 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5478 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5479 varr = &vArray[foff]; 5480 if (clperm) { 5481 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 5482 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 5483 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 5484 } else { 5485 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 5486 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 5487 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 5488 } 5489 offset += fdof; 5490 } 5491 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5492 } 5493 *size = offset; 5494 PetscFunctionReturn(0); 5495 } 5496 5497 /*@C 5498 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5499 5500 Not collective 5501 5502 Input Parameters: 5503 + dm - The DM 5504 . section - The section describing the layout in v, or NULL to use the default section 5505 . v - The local vector 5506 . point - The point in the DM 5507 . csize - The size of the input values array, or NULL 5508 - values - An array to use for the values, or NULL to have it allocated automatically 5509 5510 Output Parameters: 5511 + csize - The number of values in the closure 5512 - values - The array of values. If the user provided NULL, it is a borrowed array and should not be freed 5513 5514 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 5515 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 5516 $ assembly function, and a user may already have allocated storage for this operation. 5517 $ 5518 $ A typical use could be 5519 $ 5520 $ values = NULL; 5521 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5522 $ for (cl = 0; cl < clSize; ++cl) { 5523 $ <Compute on closure> 5524 $ } 5525 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5526 $ 5527 $ or 5528 $ 5529 $ PetscMalloc1(clMaxSize, &values); 5530 $ for (p = pStart; p < pEnd; ++p) { 5531 $ clSize = clMaxSize; 5532 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5533 $ for (cl = 0; cl < clSize; ++cl) { 5534 $ <Compute on closure> 5535 $ } 5536 $ } 5537 $ PetscFree(values); 5538 5539 Fortran Notes: 5540 Since it returns an array, this routine is only available in Fortran 90, and you must 5541 include petsc.h90 in your code. 5542 5543 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5544 5545 Level: intermediate 5546 5547 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5548 @*/ 5549 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5550 { 5551 PetscSection clSection; 5552 IS clPoints; 5553 PetscInt *points = NULL; 5554 const PetscInt *clp, *perm; 5555 PetscInt depth, numFields, numPoints, asize; 5556 PetscErrorCode ierr; 5557 5558 PetscFunctionBeginHot; 5559 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5560 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5561 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5562 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5563 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5564 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5565 if (depth == 1 && numFields < 2) { 5566 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5567 PetscFunctionReturn(0); 5568 } 5569 /* Get points */ 5570 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5571 /* Get sizes */ 5572 asize = 0; 5573 for (PetscInt p = 0; p < numPoints*2; p += 2) { 5574 PetscInt dof; 5575 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5576 asize += dof; 5577 } 5578 if (values) { 5579 const PetscScalar *vArray; 5580 PetscInt size; 5581 5582 if (*values) { 5583 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); 5584 } else {ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, values);CHKERRQ(ierr);} 5585 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm);CHKERRQ(ierr); 5586 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5587 /* Get values */ 5588 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values);CHKERRQ(ierr);} 5589 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values);CHKERRQ(ierr);} 5590 if (PetscUnlikely(asize != size)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size); 5591 /* Cleanup array */ 5592 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5593 } 5594 if (csize) *csize = asize; 5595 /* Cleanup points */ 5596 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5597 PetscFunctionReturn(0); 5598 } 5599 5600 PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5601 { 5602 DMLabel depthLabel; 5603 PetscSection clSection; 5604 IS clPoints; 5605 PetscScalar *array; 5606 const PetscScalar *vArray; 5607 PetscInt *points = NULL; 5608 const PetscInt *clp, *perm = NULL; 5609 PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5610 PetscErrorCode ierr; 5611 5612 PetscFunctionBeginHot; 5613 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5614 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5615 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5616 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5617 ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr); 5618 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 5619 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5620 if (mdepth == 1 && numFields < 2) { 5621 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5622 PetscFunctionReturn(0); 5623 } 5624 /* Get points */ 5625 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5626 for (clsize=0,p=0; p<Np; p++) { 5627 PetscInt dof; 5628 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 5629 clsize += dof; 5630 } 5631 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm);CHKERRQ(ierr); 5632 /* Filter points */ 5633 for (p = 0; p < numPoints*2; p += 2) { 5634 PetscInt dep; 5635 5636 ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr); 5637 if (dep != depth) continue; 5638 points[Np*2+0] = points[p]; 5639 points[Np*2+1] = points[p+1]; 5640 ++Np; 5641 } 5642 /* Get array */ 5643 if (!values || !*values) { 5644 PetscInt asize = 0, dof; 5645 5646 for (p = 0; p < Np*2; p += 2) { 5647 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5648 asize += dof; 5649 } 5650 if (!values) { 5651 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5652 if (csize) *csize = asize; 5653 PetscFunctionReturn(0); 5654 } 5655 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 5656 } else { 5657 array = *values; 5658 } 5659 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5660 /* Get values */ 5661 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 5662 else {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);} 5663 /* Cleanup points */ 5664 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5665 /* Cleanup array */ 5666 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5667 if (!*values) { 5668 if (csize) *csize = size; 5669 *values = array; 5670 } else { 5671 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5672 *csize = size; 5673 } 5674 PetscFunctionReturn(0); 5675 } 5676 5677 /*@C 5678 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5679 5680 Not collective 5681 5682 Input Parameters: 5683 + dm - The DM 5684 . section - The section describing the layout in v, or NULL to use the default section 5685 . v - The local vector 5686 . point - The point in the DM 5687 . csize - The number of values in the closure, or NULL 5688 - values - The array of values, which is a borrowed array and should not be freed 5689 5690 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 5691 5692 Fortran Notes: 5693 Since it returns an array, this routine is only available in Fortran 90, and you must 5694 include petsc.h90 in your code. 5695 5696 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5697 5698 Level: intermediate 5699 5700 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5701 @*/ 5702 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5703 { 5704 PetscInt size = 0; 5705 PetscErrorCode ierr; 5706 5707 PetscFunctionBegin; 5708 /* Should work without recalculating size */ 5709 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 5710 *values = NULL; 5711 PetscFunctionReturn(0); 5712 } 5713 5714 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 5715 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5716 5717 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[]) 5718 { 5719 PetscInt cdof; /* The number of constraints on this point */ 5720 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5721 PetscScalar *a; 5722 PetscInt off, cind = 0, k; 5723 PetscErrorCode ierr; 5724 5725 PetscFunctionBegin; 5726 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5727 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5728 a = &array[off]; 5729 if (!cdof || setBC) { 5730 if (clperm) { 5731 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 5732 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5733 } else { 5734 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 5735 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5736 } 5737 } else { 5738 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5739 if (clperm) { 5740 if (perm) {for (k = 0; k < dof; ++k) { 5741 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5742 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5743 } 5744 } else { 5745 for (k = 0; k < dof; ++k) { 5746 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5747 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5748 } 5749 } 5750 } else { 5751 if (perm) { 5752 for (k = 0; k < dof; ++k) { 5753 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5754 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5755 } 5756 } else { 5757 for (k = 0; k < dof; ++k) { 5758 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5759 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5760 } 5761 } 5762 } 5763 } 5764 PetscFunctionReturn(0); 5765 } 5766 5767 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[]) 5768 { 5769 PetscInt cdof; /* The number of constraints on this point */ 5770 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5771 PetscScalar *a; 5772 PetscInt off, cind = 0, k; 5773 PetscErrorCode ierr; 5774 5775 PetscFunctionBegin; 5776 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5777 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5778 a = &array[off]; 5779 if (cdof) { 5780 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5781 if (clperm) { 5782 if (perm) { 5783 for (k = 0; k < dof; ++k) { 5784 if ((cind < cdof) && (k == cdofs[cind])) { 5785 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5786 cind++; 5787 } 5788 } 5789 } else { 5790 for (k = 0; k < dof; ++k) { 5791 if ((cind < cdof) && (k == cdofs[cind])) { 5792 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5793 cind++; 5794 } 5795 } 5796 } 5797 } else { 5798 if (perm) { 5799 for (k = 0; k < dof; ++k) { 5800 if ((cind < cdof) && (k == cdofs[cind])) { 5801 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5802 cind++; 5803 } 5804 } 5805 } else { 5806 for (k = 0; k < dof; ++k) { 5807 if ((cind < cdof) && (k == cdofs[cind])) { 5808 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5809 cind++; 5810 } 5811 } 5812 } 5813 } 5814 } 5815 PetscFunctionReturn(0); 5816 } 5817 5818 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[]) 5819 { 5820 PetscScalar *a; 5821 PetscInt fdof, foff, fcdof, foffset = *offset; 5822 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5823 PetscInt cind = 0, b; 5824 PetscErrorCode ierr; 5825 5826 PetscFunctionBegin; 5827 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5828 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 5829 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5830 a = &array[foff]; 5831 if (!fcdof || setBC) { 5832 if (clperm) { 5833 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 5834 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 5835 } else { 5836 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 5837 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 5838 } 5839 } else { 5840 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5841 if (clperm) { 5842 if (perm) { 5843 for (b = 0; b < fdof; b++) { 5844 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5845 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 5846 } 5847 } else { 5848 for (b = 0; b < fdof; b++) { 5849 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5850 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 5851 } 5852 } 5853 } else { 5854 if (perm) { 5855 for (b = 0; b < fdof; b++) { 5856 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5857 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 5858 } 5859 } else { 5860 for (b = 0; b < fdof; b++) { 5861 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5862 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 5863 } 5864 } 5865 } 5866 } 5867 *offset += fdof; 5868 PetscFunctionReturn(0); 5869 } 5870 5871 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[]) 5872 { 5873 PetscScalar *a; 5874 PetscInt fdof, foff, fcdof, foffset = *offset; 5875 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5876 PetscInt Nc, cind = 0, ncind = 0, b; 5877 PetscBool ncSet, fcSet; 5878 PetscErrorCode ierr; 5879 5880 PetscFunctionBegin; 5881 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 5882 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5883 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 5884 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5885 a = &array[foff]; 5886 if (fcdof) { 5887 /* We just override fcdof and fcdofs with Ncc and comps */ 5888 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5889 if (clperm) { 5890 if (perm) { 5891 if (comps) { 5892 for (b = 0; b < fdof; b++) { 5893 ncSet = fcSet = PETSC_FALSE; 5894 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5895 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5896 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 5897 } 5898 } else { 5899 for (b = 0; b < fdof; b++) { 5900 if ((cind < fcdof) && (b == fcdofs[cind])) { 5901 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 5902 ++cind; 5903 } 5904 } 5905 } 5906 } else { 5907 if (comps) { 5908 for (b = 0; b < fdof; b++) { 5909 ncSet = fcSet = PETSC_FALSE; 5910 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5911 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5912 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 5913 } 5914 } else { 5915 for (b = 0; b < fdof; b++) { 5916 if ((cind < fcdof) && (b == fcdofs[cind])) { 5917 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 5918 ++cind; 5919 } 5920 } 5921 } 5922 } 5923 } else { 5924 if (perm) { 5925 if (comps) { 5926 for (b = 0; b < fdof; b++) { 5927 ncSet = fcSet = PETSC_FALSE; 5928 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5929 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5930 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 5931 } 5932 } else { 5933 for (b = 0; b < fdof; b++) { 5934 if ((cind < fcdof) && (b == fcdofs[cind])) { 5935 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 5936 ++cind; 5937 } 5938 } 5939 } 5940 } else { 5941 if (comps) { 5942 for (b = 0; b < fdof; b++) { 5943 ncSet = fcSet = PETSC_FALSE; 5944 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5945 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5946 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 5947 } 5948 } else { 5949 for (b = 0; b < fdof; b++) { 5950 if ((cind < fcdof) && (b == fcdofs[cind])) { 5951 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 5952 ++cind; 5953 } 5954 } 5955 } 5956 } 5957 } 5958 } 5959 *offset += fdof; 5960 PetscFunctionReturn(0); 5961 } 5962 5963 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 5964 { 5965 PetscScalar *array; 5966 const PetscInt *cone, *coneO; 5967 PetscInt pStart, pEnd, p, numPoints, off, dof; 5968 PetscErrorCode ierr; 5969 5970 PetscFunctionBeginHot; 5971 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5972 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5973 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5974 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5975 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 5976 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 5977 const PetscInt cp = !p ? point : cone[p-1]; 5978 const PetscInt o = !p ? 0 : coneO[p-1]; 5979 5980 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 5981 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5982 /* ADD_VALUES */ 5983 { 5984 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5985 PetscScalar *a; 5986 PetscInt cdof, coff, cind = 0, k; 5987 5988 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 5989 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 5990 a = &array[coff]; 5991 if (!cdof) { 5992 if (o >= 0) { 5993 for (k = 0; k < dof; ++k) { 5994 a[k] += values[off+k]; 5995 } 5996 } else { 5997 for (k = 0; k < dof; ++k) { 5998 a[k] += values[off+dof-k-1]; 5999 } 6000 } 6001 } else { 6002 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 6003 if (o >= 0) { 6004 for (k = 0; k < dof; ++k) { 6005 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6006 a[k] += values[off+k]; 6007 } 6008 } else { 6009 for (k = 0; k < dof; ++k) { 6010 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6011 a[k] += values[off+dof-k-1]; 6012 } 6013 } 6014 } 6015 } 6016 } 6017 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6018 PetscFunctionReturn(0); 6019 } 6020 6021 /*@C 6022 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6023 6024 Not collective 6025 6026 Input Parameters: 6027 + dm - The DM 6028 . section - The section describing the layout in v, or NULL to use the default section 6029 . v - The local vector 6030 . point - The point in the DM 6031 . values - The array of values 6032 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 6033 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 6034 6035 Fortran Notes: 6036 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6037 6038 Level: intermediate 6039 6040 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6041 @*/ 6042 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6043 { 6044 PetscSection clSection; 6045 IS clPoints; 6046 PetscScalar *array; 6047 PetscInt *points = NULL; 6048 const PetscInt *clp, *clperm = NULL; 6049 PetscInt depth, numFields, numPoints, p, clsize; 6050 PetscErrorCode ierr; 6051 6052 PetscFunctionBeginHot; 6053 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6054 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6055 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6056 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6057 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6058 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6059 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 6060 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 6061 PetscFunctionReturn(0); 6062 } 6063 /* Get points */ 6064 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6065 for (clsize=0,p=0; p<numPoints; p++) { 6066 PetscInt dof; 6067 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 6068 clsize += dof; 6069 } 6070 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 6071 /* Get array */ 6072 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6073 /* Get values */ 6074 if (numFields > 0) { 6075 PetscInt offset = 0, f; 6076 for (f = 0; f < numFields; ++f) { 6077 const PetscInt **perms = NULL; 6078 const PetscScalar **flips = NULL; 6079 6080 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6081 switch (mode) { 6082 case INSERT_VALUES: 6083 for (p = 0; p < numPoints; p++) { 6084 const PetscInt point = points[2*p]; 6085 const PetscInt *perm = perms ? perms[p] : NULL; 6086 const PetscScalar *flip = flips ? flips[p] : NULL; 6087 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6088 } break; 6089 case INSERT_ALL_VALUES: 6090 for (p = 0; p < numPoints; p++) { 6091 const PetscInt point = points[2*p]; 6092 const PetscInt *perm = perms ? perms[p] : NULL; 6093 const PetscScalar *flip = flips ? flips[p] : NULL; 6094 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6095 } break; 6096 case INSERT_BC_VALUES: 6097 for (p = 0; p < numPoints; p++) { 6098 const PetscInt point = points[2*p]; 6099 const PetscInt *perm = perms ? perms[p] : NULL; 6100 const PetscScalar *flip = flips ? flips[p] : NULL; 6101 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6102 } break; 6103 case ADD_VALUES: 6104 for (p = 0; p < numPoints; p++) { 6105 const PetscInt point = points[2*p]; 6106 const PetscInt *perm = perms ? perms[p] : NULL; 6107 const PetscScalar *flip = flips ? flips[p] : NULL; 6108 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6109 } break; 6110 case ADD_ALL_VALUES: 6111 for (p = 0; p < numPoints; p++) { 6112 const PetscInt point = points[2*p]; 6113 const PetscInt *perm = perms ? perms[p] : NULL; 6114 const PetscScalar *flip = flips ? flips[p] : NULL; 6115 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6116 } break; 6117 case ADD_BC_VALUES: 6118 for (p = 0; p < numPoints; p++) { 6119 const PetscInt point = points[2*p]; 6120 const PetscInt *perm = perms ? perms[p] : NULL; 6121 const PetscScalar *flip = flips ? flips[p] : NULL; 6122 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6123 } break; 6124 default: 6125 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6126 } 6127 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6128 } 6129 } else { 6130 PetscInt dof, off; 6131 const PetscInt **perms = NULL; 6132 const PetscScalar **flips = NULL; 6133 6134 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6135 switch (mode) { 6136 case INSERT_VALUES: 6137 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6138 const PetscInt point = points[2*p]; 6139 const PetscInt *perm = perms ? perms[p] : NULL; 6140 const PetscScalar *flip = flips ? flips[p] : NULL; 6141 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6142 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6143 } break; 6144 case INSERT_ALL_VALUES: 6145 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6146 const PetscInt point = points[2*p]; 6147 const PetscInt *perm = perms ? perms[p] : NULL; 6148 const PetscScalar *flip = flips ? flips[p] : NULL; 6149 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6150 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6151 } break; 6152 case INSERT_BC_VALUES: 6153 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6154 const PetscInt point = points[2*p]; 6155 const PetscInt *perm = perms ? perms[p] : NULL; 6156 const PetscScalar *flip = flips ? flips[p] : NULL; 6157 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6158 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6159 } break; 6160 case ADD_VALUES: 6161 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6162 const PetscInt point = points[2*p]; 6163 const PetscInt *perm = perms ? perms[p] : NULL; 6164 const PetscScalar *flip = flips ? flips[p] : NULL; 6165 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6166 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6167 } break; 6168 case ADD_ALL_VALUES: 6169 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6170 const PetscInt point = points[2*p]; 6171 const PetscInt *perm = perms ? perms[p] : NULL; 6172 const PetscScalar *flip = flips ? flips[p] : NULL; 6173 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6174 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6175 } break; 6176 case ADD_BC_VALUES: 6177 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6178 const PetscInt point = points[2*p]; 6179 const PetscInt *perm = perms ? perms[p] : NULL; 6180 const PetscScalar *flip = flips ? flips[p] : NULL; 6181 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6182 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6183 } break; 6184 default: 6185 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6186 } 6187 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6188 } 6189 /* Cleanup points */ 6190 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6191 /* Cleanup array */ 6192 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6193 PetscFunctionReturn(0); 6194 } 6195 6196 /* Check whether the given point is in the label. If not, update the offset to skip this point */ 6197 PETSC_STATIC_INLINE PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 6198 { 6199 PetscFunctionBegin; 6200 if (label) { 6201 PetscInt val, fdof; 6202 PetscErrorCode ierr; 6203 6204 /* There is a problem with this: 6205 Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that 6206 touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell. 6207 Thus I am only going to check val != -1, not val != labelId 6208 */ 6209 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 6210 if (val < 0) { 6211 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6212 *offset += fdof; 6213 PetscFunctionReturn(1); 6214 } 6215 } 6216 PetscFunctionReturn(0); 6217 } 6218 6219 /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 6220 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) 6221 { 6222 PetscSection clSection; 6223 IS clPoints; 6224 PetscScalar *array; 6225 PetscInt *points = NULL; 6226 const PetscInt *clp; 6227 PetscInt numFields, numPoints, p; 6228 PetscInt offset = 0, f; 6229 PetscErrorCode ierr; 6230 6231 PetscFunctionBeginHot; 6232 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6233 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6234 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6235 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6236 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6237 /* Get points */ 6238 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6239 /* Get array */ 6240 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6241 /* Get values */ 6242 for (f = 0; f < numFields; ++f) { 6243 const PetscInt **perms = NULL; 6244 const PetscScalar **flips = NULL; 6245 6246 if (!fieldActive[f]) { 6247 for (p = 0; p < numPoints*2; p += 2) { 6248 PetscInt fdof; 6249 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6250 offset += fdof; 6251 } 6252 continue; 6253 } 6254 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6255 switch (mode) { 6256 case INSERT_VALUES: 6257 for (p = 0; p < numPoints; p++) { 6258 const PetscInt point = points[2*p]; 6259 const PetscInt *perm = perms ? perms[p] : NULL; 6260 const PetscScalar *flip = flips ? flips[p] : NULL; 6261 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6262 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array); 6263 } break; 6264 case INSERT_ALL_VALUES: 6265 for (p = 0; p < numPoints; p++) { 6266 const PetscInt point = points[2*p]; 6267 const PetscInt *perm = perms ? perms[p] : NULL; 6268 const PetscScalar *flip = flips ? flips[p] : NULL; 6269 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6270 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array); 6271 } break; 6272 case INSERT_BC_VALUES: 6273 for (p = 0; p < numPoints; p++) { 6274 const PetscInt point = points[2*p]; 6275 const PetscInt *perm = perms ? perms[p] : NULL; 6276 const PetscScalar *flip = flips ? flips[p] : NULL; 6277 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6278 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array); 6279 } break; 6280 case ADD_VALUES: 6281 for (p = 0; p < numPoints; p++) { 6282 const PetscInt point = points[2*p]; 6283 const PetscInt *perm = perms ? perms[p] : NULL; 6284 const PetscScalar *flip = flips ? flips[p] : NULL; 6285 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6286 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array); 6287 } break; 6288 case ADD_ALL_VALUES: 6289 for (p = 0; p < numPoints; p++) { 6290 const PetscInt point = points[2*p]; 6291 const PetscInt *perm = perms ? perms[p] : NULL; 6292 const PetscScalar *flip = flips ? flips[p] : NULL; 6293 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6294 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array); 6295 } break; 6296 default: 6297 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6298 } 6299 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6300 } 6301 /* Cleanup points */ 6302 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6303 /* Cleanup array */ 6304 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6305 PetscFunctionReturn(0); 6306 } 6307 6308 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6309 { 6310 PetscMPIInt rank; 6311 PetscInt i, j; 6312 PetscErrorCode ierr; 6313 6314 PetscFunctionBegin; 6315 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr); 6316 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 6317 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 6318 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 6319 numCIndices = numCIndices ? numCIndices : numRIndices; 6320 if (!values) PetscFunctionReturn(0); 6321 for (i = 0; i < numRIndices; i++) { 6322 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 6323 for (j = 0; j < numCIndices; j++) { 6324 #if defined(PETSC_USE_COMPLEX) 6325 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 6326 #else 6327 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 6328 #endif 6329 } 6330 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6331 } 6332 PetscFunctionReturn(0); 6333 } 6334 6335 /* 6336 DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 6337 6338 Input Parameters: 6339 + section - The section for this data layout 6340 . islocal - Is the section (and thus indices being requested) local or global? 6341 . point - The point contributing dofs with these indices 6342 . off - The global offset of this point 6343 . loff - The local offset of each field 6344 . setBC - The flag determining whether to include indices of bounsary values 6345 . perm - A permutation of the dofs on this point, or NULL 6346 - indperm - A permutation of the entire indices array, or NULL 6347 6348 Output Parameter: 6349 . indices - Indices for dofs on this point 6350 6351 Level: developer 6352 6353 Note: The indices could be local or global, depending on the value of 'off'. 6354 */ 6355 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6356 { 6357 PetscInt dof; /* The number of unknowns on this point */ 6358 PetscInt cdof; /* The number of constraints on this point */ 6359 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6360 PetscInt cind = 0, k; 6361 PetscErrorCode ierr; 6362 6363 PetscFunctionBegin; 6364 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6365 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6366 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6367 if (!cdof || setBC) { 6368 for (k = 0; k < dof; ++k) { 6369 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6370 const PetscInt ind = indperm ? indperm[preind] : preind; 6371 6372 indices[ind] = off + k; 6373 } 6374 } else { 6375 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6376 for (k = 0; k < dof; ++k) { 6377 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6378 const PetscInt ind = indperm ? indperm[preind] : preind; 6379 6380 if ((cind < cdof) && (k == cdofs[cind])) { 6381 /* Insert check for returning constrained indices */ 6382 indices[ind] = -(off+k+1); 6383 ++cind; 6384 } else { 6385 indices[ind] = off + k - (islocal ? 0 : cind); 6386 } 6387 } 6388 } 6389 *loff += dof; 6390 PetscFunctionReturn(0); 6391 } 6392 6393 /* 6394 DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 6395 6396 Input Parameters: 6397 + section - a section (global or local) 6398 - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 6399 . point - point within section 6400 . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 6401 . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 6402 . setBC - identify constrained (boundary condition) points via involution. 6403 . perms - perms[f][permsoff][:] is a permutation of dofs within each field 6404 . permsoff - offset 6405 - indperm - index permutation 6406 6407 Output Parameter: 6408 . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 6409 . indices - array to hold indices (as defined by section) of each dof associated with point 6410 6411 Notes: 6412 If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 6413 If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 6414 in the local vector. 6415 6416 If section is global and setBC=false, the indices for constrained points are negative (and their value is not 6417 significant). It is invalid to call with a global section and setBC=true. 6418 6419 Developer Note: 6420 The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 6421 in the future, global sections may have fields set, in which case we could pass the global section and obtain the 6422 offset could be obtained from the section instead of passing it explicitly as we do now. 6423 6424 Example: 6425 Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 6426 When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 6427 Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 6428 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. 6429 6430 Level: developer 6431 */ 6432 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[]) 6433 { 6434 PetscInt numFields, foff, f; 6435 PetscErrorCode ierr; 6436 6437 PetscFunctionBegin; 6438 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6439 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6440 for (f = 0, foff = 0; f < numFields; ++f) { 6441 PetscInt fdof, cfdof; 6442 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6443 PetscInt cind = 0, b; 6444 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6445 6446 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6447 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6448 if (!cfdof || setBC) { 6449 for (b = 0; b < fdof; ++b) { 6450 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6451 const PetscInt ind = indperm ? indperm[preind] : preind; 6452 6453 indices[ind] = off+foff+b; 6454 } 6455 } else { 6456 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6457 for (b = 0; b < fdof; ++b) { 6458 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6459 const PetscInt ind = indperm ? indperm[preind] : preind; 6460 6461 if ((cind < cfdof) && (b == fcdofs[cind])) { 6462 indices[ind] = -(off+foff+b+1); 6463 ++cind; 6464 } else { 6465 indices[ind] = off + foff + b - (islocal ? 0 : cind); 6466 } 6467 } 6468 } 6469 foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6470 foffs[f] += fdof; 6471 } 6472 PetscFunctionReturn(0); 6473 } 6474 6475 /* 6476 This version believes the globalSection offsets for each field, rather than just the point offset 6477 6478 . foffs - The offset into 'indices' for each field, since it is segregated by field 6479 6480 Notes: 6481 The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6482 Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 6483 */ 6484 static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 6485 { 6486 PetscInt numFields, foff, f; 6487 PetscErrorCode ierr; 6488 6489 PetscFunctionBegin; 6490 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6491 for (f = 0; f < numFields; ++f) { 6492 PetscInt fdof, cfdof; 6493 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6494 PetscInt cind = 0, b; 6495 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6496 6497 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6498 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6499 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 6500 if (!cfdof) { 6501 for (b = 0; b < fdof; ++b) { 6502 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6503 const PetscInt ind = indperm ? indperm[preind] : preind; 6504 6505 indices[ind] = foff+b; 6506 } 6507 } else { 6508 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6509 for (b = 0; b < fdof; ++b) { 6510 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6511 const PetscInt ind = indperm ? indperm[preind] : preind; 6512 6513 if ((cind < cfdof) && (b == fcdofs[cind])) { 6514 indices[ind] = -(foff+b+1); 6515 ++cind; 6516 } else { 6517 indices[ind] = foff+b-cind; 6518 } 6519 } 6520 } 6521 foffs[f] += fdof; 6522 } 6523 PetscFunctionReturn(0); 6524 } 6525 6526 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) 6527 { 6528 Mat cMat; 6529 PetscSection aSec, cSec; 6530 IS aIS; 6531 PetscInt aStart = -1, aEnd = -1; 6532 const PetscInt *anchors; 6533 PetscInt numFields, f, p, q, newP = 0; 6534 PetscInt newNumPoints = 0, newNumIndices = 0; 6535 PetscInt *newPoints, *indices, *newIndices; 6536 PetscInt maxAnchor, maxDof; 6537 PetscInt newOffsets[32]; 6538 PetscInt *pointMatOffsets[32]; 6539 PetscInt *newPointOffsets[32]; 6540 PetscScalar *pointMat[32]; 6541 PetscScalar *newValues=NULL,*tmpValues; 6542 PetscBool anyConstrained = PETSC_FALSE; 6543 PetscErrorCode ierr; 6544 6545 PetscFunctionBegin; 6546 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6547 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6548 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6549 6550 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6551 /* if there are point-to-point constraints */ 6552 if (aSec) { 6553 ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr); 6554 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6555 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 6556 /* figure out how many points are going to be in the new element matrix 6557 * (we allow double counting, because it's all just going to be summed 6558 * into the global matrix anyway) */ 6559 for (p = 0; p < 2*numPoints; p+=2) { 6560 PetscInt b = points[p]; 6561 PetscInt bDof = 0, bSecDof; 6562 6563 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6564 if (!bSecDof) { 6565 continue; 6566 } 6567 if (b >= aStart && b < aEnd) { 6568 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 6569 } 6570 if (bDof) { 6571 /* this point is constrained */ 6572 /* it is going to be replaced by its anchors */ 6573 PetscInt bOff, q; 6574 6575 anyConstrained = PETSC_TRUE; 6576 newNumPoints += bDof; 6577 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 6578 for (q = 0; q < bDof; q++) { 6579 PetscInt a = anchors[bOff + q]; 6580 PetscInt aDof; 6581 6582 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6583 newNumIndices += aDof; 6584 for (f = 0; f < numFields; ++f) { 6585 PetscInt fDof; 6586 6587 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 6588 newOffsets[f+1] += fDof; 6589 } 6590 } 6591 } 6592 else { 6593 /* this point is not constrained */ 6594 newNumPoints++; 6595 newNumIndices += bSecDof; 6596 for (f = 0; f < numFields; ++f) { 6597 PetscInt fDof; 6598 6599 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6600 newOffsets[f+1] += fDof; 6601 } 6602 } 6603 } 6604 } 6605 if (!anyConstrained) { 6606 if (outNumPoints) *outNumPoints = 0; 6607 if (outNumIndices) *outNumIndices = 0; 6608 if (outPoints) *outPoints = NULL; 6609 if (outValues) *outValues = NULL; 6610 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6611 PetscFunctionReturn(0); 6612 } 6613 6614 if (outNumPoints) *outNumPoints = newNumPoints; 6615 if (outNumIndices) *outNumIndices = newNumIndices; 6616 6617 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6618 6619 if (!outPoints && !outValues) { 6620 if (offsets) { 6621 for (f = 0; f <= numFields; f++) { 6622 offsets[f] = newOffsets[f]; 6623 } 6624 } 6625 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6626 PetscFunctionReturn(0); 6627 } 6628 6629 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 6630 6631 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 6632 6633 /* workspaces */ 6634 if (numFields) { 6635 for (f = 0; f < numFields; f++) { 6636 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 6637 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6638 } 6639 } 6640 else { 6641 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 6642 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6643 } 6644 6645 /* get workspaces for the point-to-point matrices */ 6646 if (numFields) { 6647 PetscInt totalOffset, totalMatOffset; 6648 6649 for (p = 0; p < numPoints; p++) { 6650 PetscInt b = points[2*p]; 6651 PetscInt bDof = 0, bSecDof; 6652 6653 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6654 if (!bSecDof) { 6655 for (f = 0; f < numFields; f++) { 6656 newPointOffsets[f][p + 1] = 0; 6657 pointMatOffsets[f][p + 1] = 0; 6658 } 6659 continue; 6660 } 6661 if (b >= aStart && b < aEnd) { 6662 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6663 } 6664 if (bDof) { 6665 for (f = 0; f < numFields; f++) { 6666 PetscInt fDof, q, bOff, allFDof = 0; 6667 6668 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6669 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6670 for (q = 0; q < bDof; q++) { 6671 PetscInt a = anchors[bOff + q]; 6672 PetscInt aFDof; 6673 6674 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 6675 allFDof += aFDof; 6676 } 6677 newPointOffsets[f][p+1] = allFDof; 6678 pointMatOffsets[f][p+1] = fDof * allFDof; 6679 } 6680 } 6681 else { 6682 for (f = 0; f < numFields; f++) { 6683 PetscInt fDof; 6684 6685 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6686 newPointOffsets[f][p+1] = fDof; 6687 pointMatOffsets[f][p+1] = 0; 6688 } 6689 } 6690 } 6691 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 6692 newPointOffsets[f][0] = totalOffset; 6693 pointMatOffsets[f][0] = totalMatOffset; 6694 for (p = 0; p < numPoints; p++) { 6695 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6696 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6697 } 6698 totalOffset = newPointOffsets[f][numPoints]; 6699 totalMatOffset = pointMatOffsets[f][numPoints]; 6700 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 6701 } 6702 } 6703 else { 6704 for (p = 0; p < numPoints; p++) { 6705 PetscInt b = points[2*p]; 6706 PetscInt bDof = 0, bSecDof; 6707 6708 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6709 if (!bSecDof) { 6710 newPointOffsets[0][p + 1] = 0; 6711 pointMatOffsets[0][p + 1] = 0; 6712 continue; 6713 } 6714 if (b >= aStart && b < aEnd) { 6715 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6716 } 6717 if (bDof) { 6718 PetscInt bOff, q, allDof = 0; 6719 6720 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6721 for (q = 0; q < bDof; q++) { 6722 PetscInt a = anchors[bOff + q], aDof; 6723 6724 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 6725 allDof += aDof; 6726 } 6727 newPointOffsets[0][p+1] = allDof; 6728 pointMatOffsets[0][p+1] = bSecDof * allDof; 6729 } 6730 else { 6731 newPointOffsets[0][p+1] = bSecDof; 6732 pointMatOffsets[0][p+1] = 0; 6733 } 6734 } 6735 newPointOffsets[0][0] = 0; 6736 pointMatOffsets[0][0] = 0; 6737 for (p = 0; p < numPoints; p++) { 6738 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6739 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6740 } 6741 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 6742 } 6743 6744 /* output arrays */ 6745 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6746 6747 /* get the point-to-point matrices; construct newPoints */ 6748 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 6749 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6750 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 6751 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 6752 if (numFields) { 6753 for (p = 0, newP = 0; p < numPoints; p++) { 6754 PetscInt b = points[2*p]; 6755 PetscInt o = points[2*p+1]; 6756 PetscInt bDof = 0, bSecDof; 6757 6758 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6759 if (!bSecDof) { 6760 continue; 6761 } 6762 if (b >= aStart && b < aEnd) { 6763 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6764 } 6765 if (bDof) { 6766 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6767 6768 fStart[0] = 0; 6769 fEnd[0] = 0; 6770 for (f = 0; f < numFields; f++) { 6771 PetscInt fDof; 6772 6773 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 6774 fStart[f+1] = fStart[f] + fDof; 6775 fEnd[f+1] = fStart[f+1]; 6776 } 6777 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6778 ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 6779 6780 fAnchorStart[0] = 0; 6781 fAnchorEnd[0] = 0; 6782 for (f = 0; f < numFields; f++) { 6783 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 6784 6785 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 6786 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 6787 } 6788 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6789 for (q = 0; q < bDof; q++) { 6790 PetscInt a = anchors[bOff + q], aOff; 6791 6792 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6793 newPoints[2*(newP + q)] = a; 6794 newPoints[2*(newP + q) + 1] = 0; 6795 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 6796 ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 6797 } 6798 newP += bDof; 6799 6800 if (outValues) { 6801 /* get the point-to-point submatrix */ 6802 for (f = 0; f < numFields; f++) { 6803 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 6804 } 6805 } 6806 } 6807 else { 6808 newPoints[2 * newP] = b; 6809 newPoints[2 * newP + 1] = o; 6810 newP++; 6811 } 6812 } 6813 } else { 6814 for (p = 0; p < numPoints; p++) { 6815 PetscInt b = points[2*p]; 6816 PetscInt o = points[2*p+1]; 6817 PetscInt bDof = 0, bSecDof; 6818 6819 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6820 if (!bSecDof) { 6821 continue; 6822 } 6823 if (b >= aStart && b < aEnd) { 6824 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6825 } 6826 if (bDof) { 6827 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 6828 6829 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6830 ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 6831 6832 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 6833 for (q = 0; q < bDof; q++) { 6834 PetscInt a = anchors[bOff + q], aOff; 6835 6836 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6837 6838 newPoints[2*(newP + q)] = a; 6839 newPoints[2*(newP + q) + 1] = 0; 6840 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 6841 ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 6842 } 6843 newP += bDof; 6844 6845 /* get the point-to-point submatrix */ 6846 if (outValues) { 6847 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 6848 } 6849 } 6850 else { 6851 newPoints[2 * newP] = b; 6852 newPoints[2 * newP + 1] = o; 6853 newP++; 6854 } 6855 } 6856 } 6857 6858 if (outValues) { 6859 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 6860 ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr); 6861 /* multiply constraints on the right */ 6862 if (numFields) { 6863 for (f = 0; f < numFields; f++) { 6864 PetscInt oldOff = offsets[f]; 6865 6866 for (p = 0; p < numPoints; p++) { 6867 PetscInt cStart = newPointOffsets[f][p]; 6868 PetscInt b = points[2 * p]; 6869 PetscInt c, r, k; 6870 PetscInt dof; 6871 6872 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 6873 if (!dof) { 6874 continue; 6875 } 6876 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 6877 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 6878 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 6879 6880 for (r = 0; r < numIndices; r++) { 6881 for (c = 0; c < nCols; c++) { 6882 for (k = 0; k < dof; k++) { 6883 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 6884 } 6885 } 6886 } 6887 } 6888 else { 6889 /* copy this column as is */ 6890 for (r = 0; r < numIndices; r++) { 6891 for (c = 0; c < dof; c++) { 6892 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 6893 } 6894 } 6895 } 6896 oldOff += dof; 6897 } 6898 } 6899 } 6900 else { 6901 PetscInt oldOff = 0; 6902 for (p = 0; p < numPoints; p++) { 6903 PetscInt cStart = newPointOffsets[0][p]; 6904 PetscInt b = points[2 * p]; 6905 PetscInt c, r, k; 6906 PetscInt dof; 6907 6908 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 6909 if (!dof) { 6910 continue; 6911 } 6912 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 6913 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 6914 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 6915 6916 for (r = 0; r < numIndices; r++) { 6917 for (c = 0; c < nCols; c++) { 6918 for (k = 0; k < dof; k++) { 6919 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 6920 } 6921 } 6922 } 6923 } 6924 else { 6925 /* copy this column as is */ 6926 for (r = 0; r < numIndices; r++) { 6927 for (c = 0; c < dof; c++) { 6928 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 6929 } 6930 } 6931 } 6932 oldOff += dof; 6933 } 6934 } 6935 6936 if (multiplyLeft) { 6937 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 6938 ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr); 6939 /* multiply constraints transpose on the left */ 6940 if (numFields) { 6941 for (f = 0; f < numFields; f++) { 6942 PetscInt oldOff = offsets[f]; 6943 6944 for (p = 0; p < numPoints; p++) { 6945 PetscInt rStart = newPointOffsets[f][p]; 6946 PetscInt b = points[2 * p]; 6947 PetscInt c, r, k; 6948 PetscInt dof; 6949 6950 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 6951 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 6952 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 6953 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 6954 6955 for (r = 0; r < nRows; r++) { 6956 for (c = 0; c < newNumIndices; c++) { 6957 for (k = 0; k < dof; k++) { 6958 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 6959 } 6960 } 6961 } 6962 } 6963 else { 6964 /* copy this row as is */ 6965 for (r = 0; r < dof; r++) { 6966 for (c = 0; c < newNumIndices; c++) { 6967 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 6968 } 6969 } 6970 } 6971 oldOff += dof; 6972 } 6973 } 6974 } 6975 else { 6976 PetscInt oldOff = 0; 6977 6978 for (p = 0; p < numPoints; p++) { 6979 PetscInt rStart = newPointOffsets[0][p]; 6980 PetscInt b = points[2 * p]; 6981 PetscInt c, r, k; 6982 PetscInt dof; 6983 6984 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 6985 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 6986 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 6987 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 6988 6989 for (r = 0; r < nRows; r++) { 6990 for (c = 0; c < newNumIndices; c++) { 6991 for (k = 0; k < dof; k++) { 6992 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 6993 } 6994 } 6995 } 6996 } 6997 else { 6998 /* copy this row as is */ 6999 for (r = 0; r < dof; r++) { 7000 for (c = 0; c < newNumIndices; c++) { 7001 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7002 } 7003 } 7004 } 7005 oldOff += dof; 7006 } 7007 } 7008 7009 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7010 } 7011 else { 7012 newValues = tmpValues; 7013 } 7014 } 7015 7016 /* clean up */ 7017 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 7018 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 7019 7020 if (numFields) { 7021 for (f = 0; f < numFields; f++) { 7022 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 7023 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 7024 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 7025 } 7026 } 7027 else { 7028 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 7029 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 7030 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 7031 } 7032 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7033 7034 /* output */ 7035 if (outPoints) { 7036 *outPoints = newPoints; 7037 } 7038 else { 7039 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 7040 } 7041 if (outValues) { 7042 *outValues = newValues; 7043 } 7044 for (f = 0; f <= numFields; f++) { 7045 offsets[f] = newOffsets[f]; 7046 } 7047 PetscFunctionReturn(0); 7048 } 7049 7050 /*@C 7051 DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 7052 7053 Not collective 7054 7055 Input Parameters: 7056 + dm - The DM 7057 . section - The PetscSection describing the points (a local section) 7058 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7059 . point - The point defining the closure 7060 - useClPerm - Use the closure point permutation if available 7061 7062 Output Parameters: 7063 + numIndices - The number of dof indices in the closure of point with the input sections 7064 . indices - The dof indices 7065 . outOffsets - Array to write the field offsets into, or NULL 7066 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7067 7068 Notes: 7069 Must call DMPlexRestoreClosureIndices() to free allocated memory 7070 7071 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7072 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7073 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7074 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7075 indices (with the above semantics) are implied. 7076 7077 Level: advanced 7078 7079 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7080 @*/ 7081 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7082 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7083 { 7084 /* Closure ordering */ 7085 PetscSection clSection; 7086 IS clPoints; 7087 const PetscInt *clp; 7088 PetscInt *points; 7089 const PetscInt *clperm = NULL; 7090 /* Dof permutation and sign flips */ 7091 const PetscInt **perms[32] = {NULL}; 7092 const PetscScalar **flips[32] = {NULL}; 7093 PetscScalar *valCopy = NULL; 7094 /* Hanging node constraints */ 7095 PetscInt *pointsC = NULL; 7096 PetscScalar *valuesC = NULL; 7097 PetscInt NclC, NiC; 7098 7099 PetscInt *idx; 7100 PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 7101 PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 7102 PetscErrorCode ierr; 7103 7104 PetscFunctionBeginHot; 7105 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7106 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7107 PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7108 if (numIndices) PetscValidPointer(numIndices, 6); 7109 if (indices) PetscValidPointer(indices, 7); 7110 if (outOffsets) PetscValidPointer(outOffsets, 8); 7111 if (values) PetscValidPointer(values, 9); 7112 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 7113 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 7114 ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 7115 /* 1) Get points in closure */ 7116 ierr = DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7117 if (useClPerm) { 7118 PetscInt depth, clsize; 7119 ierr = DMPlexGetPointDepth(dm, point, &depth);CHKERRQ(ierr); 7120 for (clsize=0,p=0; p<Ncl; p++) { 7121 PetscInt dof; 7122 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 7123 clsize += dof; 7124 } 7125 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 7126 } 7127 /* 2) Get number of indices on these points and field offsets from section */ 7128 for (p = 0; p < Ncl*2; p += 2) { 7129 PetscInt dof, fdof; 7130 7131 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7132 for (f = 0; f < Nf; ++f) { 7133 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7134 offsets[f+1] += fdof; 7135 } 7136 Ni += dof; 7137 } 7138 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 7139 if (Nf && offsets[Nf] != Ni) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni); 7140 /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 7141 for (f = 0; f < PetscMax(1, Nf); ++f) { 7142 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7143 else {ierr = PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7144 /* may need to apply sign changes to the element matrix */ 7145 if (values && flips[f]) { 7146 PetscInt foffset = offsets[f]; 7147 7148 for (p = 0; p < Ncl; ++p) { 7149 PetscInt pnt = points[2*p], fdof; 7150 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 7151 7152 if (!Nf) {ierr = PetscSectionGetDof(section, pnt, &fdof);CHKERRQ(ierr);} 7153 else {ierr = PetscSectionGetFieldDof(section, pnt, f, &fdof);CHKERRQ(ierr);} 7154 if (flip) { 7155 PetscInt i, j, k; 7156 7157 if (!valCopy) { 7158 ierr = DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr); 7159 for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 7160 *values = valCopy; 7161 } 7162 for (i = 0; i < fdof; ++i) { 7163 PetscScalar fval = flip[i]; 7164 7165 for (k = 0; k < Ni; ++k) { 7166 valCopy[Ni * (foffset + i) + k] *= fval; 7167 valCopy[Ni * k + (foffset + i)] *= fval; 7168 } 7169 } 7170 } 7171 foffset += fdof; 7172 } 7173 } 7174 } 7175 /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 7176 ierr = DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 7177 if (NclC) { 7178 if (valCopy) {ierr = DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);} 7179 for (f = 0; f < PetscMax(1, Nf); ++f) { 7180 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7181 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7182 } 7183 for (f = 0; f < PetscMax(1, Nf); ++f) { 7184 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7185 else {ierr = PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7186 } 7187 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7188 Ncl = NclC; 7189 Ni = NiC; 7190 points = pointsC; 7191 if (values) *values = valuesC; 7192 } 7193 /* 5) Calculate indices */ 7194 ierr = DMGetWorkArray(dm, Ni, MPIU_INT, &idx);CHKERRQ(ierr); 7195 if (Nf) { 7196 PetscInt idxOff; 7197 PetscBool useFieldOffsets; 7198 7199 if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 7200 ierr = PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets);CHKERRQ(ierr); 7201 if (useFieldOffsets) { 7202 for (p = 0; p < Ncl; ++p) { 7203 const PetscInt pnt = points[p*2]; 7204 7205 ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx);CHKERRQ(ierr); 7206 } 7207 } else { 7208 for (p = 0; p < Ncl; ++p) { 7209 const PetscInt pnt = points[p*2]; 7210 7211 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7212 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7213 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 7214 * global section. */ 7215 ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx);CHKERRQ(ierr); 7216 } 7217 } 7218 } else { 7219 PetscInt off = 0, idxOff; 7220 7221 for (p = 0; p < Ncl; ++p) { 7222 const PetscInt pnt = points[p*2]; 7223 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 7224 7225 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7226 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7227 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 7228 ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx);CHKERRQ(ierr); 7229 } 7230 } 7231 /* 6) Cleanup */ 7232 for (f = 0; f < PetscMax(1, Nf); ++f) { 7233 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7234 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7235 } 7236 if (NclC) { 7237 ierr = DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC);CHKERRQ(ierr); 7238 } else { 7239 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7240 } 7241 7242 if (numIndices) *numIndices = Ni; 7243 if (indices) *indices = idx; 7244 PetscFunctionReturn(0); 7245 } 7246 7247 /*@C 7248 DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 7249 7250 Not collective 7251 7252 Input Parameters: 7253 + dm - The DM 7254 . section - The PetscSection describing the points (a local section) 7255 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7256 . point - The point defining the closure 7257 - useClPerm - Use the closure point permutation if available 7258 7259 Output Parameters: 7260 + numIndices - The number of dof indices in the closure of point with the input sections 7261 . indices - The dof indices 7262 . outOffsets - Array to write the field offsets into, or NULL 7263 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7264 7265 Notes: 7266 If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 7267 7268 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7269 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7270 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7271 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7272 indices (with the above semantics) are implied. 7273 7274 Level: advanced 7275 7276 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7277 @*/ 7278 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7279 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7280 { 7281 PetscErrorCode ierr; 7282 7283 PetscFunctionBegin; 7284 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7285 PetscValidPointer(indices, 7); 7286 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 7287 PetscFunctionReturn(0); 7288 } 7289 7290 /*@C 7291 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 7292 7293 Not collective 7294 7295 Input Parameters: 7296 + dm - The DM 7297 . section - The section describing the layout in v, or NULL to use the default section 7298 . globalSection - The section describing the layout in v, or NULL to use the default global section 7299 . A - The matrix 7300 . point - The point in the DM 7301 . values - The array of values 7302 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7303 7304 Fortran Notes: 7305 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 7306 7307 Level: intermediate 7308 7309 .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7310 @*/ 7311 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7312 { 7313 DM_Plex *mesh = (DM_Plex*) dm->data; 7314 PetscInt *indices; 7315 PetscInt numIndices; 7316 const PetscScalar *valuesOrig = values; 7317 PetscErrorCode ierr; 7318 7319 PetscFunctionBegin; 7320 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7321 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 7322 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7323 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 7324 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 7325 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7326 7327 ierr = DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7328 7329 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 7330 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7331 if (ierr) { 7332 PetscMPIInt rank; 7333 PetscErrorCode ierr2; 7334 7335 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7336 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7337 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 7338 ierr2 = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7339 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7340 CHKERRQ(ierr); 7341 } 7342 if (mesh->printFEM > 1) { 7343 PetscInt i; 7344 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 7345 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 7346 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7347 } 7348 7349 ierr = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7350 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7351 PetscFunctionReturn(0); 7352 } 7353 7354 /*@C 7355 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 7356 7357 Not collective 7358 7359 Input Parameters: 7360 + dmRow - The DM for the row fields 7361 . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 7362 . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 7363 . dmCol - The DM for the column fields 7364 . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 7365 . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 7366 . A - The matrix 7367 . point - The point in the DMs 7368 . values - The array of values 7369 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7370 7371 Level: intermediate 7372 7373 .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7374 @*/ 7375 PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7376 { 7377 DM_Plex *mesh = (DM_Plex*) dmRow->data; 7378 PetscInt *indicesRow, *indicesCol; 7379 PetscInt numIndicesRow, numIndicesCol; 7380 const PetscScalar *valuesOrig = values; 7381 PetscErrorCode ierr; 7382 7383 PetscFunctionBegin; 7384 PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 7385 if (!sectionRow) {ierr = DMGetLocalSection(dmRow, §ionRow);CHKERRQ(ierr);} 7386 PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 7387 if (!globalSectionRow) {ierr = DMGetGlobalSection(dmRow, &globalSectionRow);CHKERRQ(ierr);} 7388 PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 7389 PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 7390 if (!sectionCol) {ierr = DMGetLocalSection(dmCol, §ionCol);CHKERRQ(ierr);} 7391 PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 7392 if (!globalSectionCol) {ierr = DMGetGlobalSection(dmCol, &globalSectionCol);CHKERRQ(ierr);} 7393 PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 7394 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7395 7396 ierr = DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7397 ierr = DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7398 7399 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr);} 7400 ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 7401 if (ierr) { 7402 PetscMPIInt rank; 7403 PetscErrorCode ierr2; 7404 7405 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7406 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7407 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr2); 7408 ierr2 = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7409 ierr2 = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7410 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7411 CHKERRQ(ierr); 7412 } 7413 7414 ierr = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7415 ierr = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7416 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7417 PetscFunctionReturn(0); 7418 } 7419 7420 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7421 { 7422 DM_Plex *mesh = (DM_Plex*) dmf->data; 7423 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7424 PetscInt *cpoints = NULL; 7425 PetscInt *findices, *cindices; 7426 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7427 PetscInt foffsets[32], coffsets[32]; 7428 DMPolytopeType ct; 7429 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7430 PetscErrorCode ierr; 7431 7432 PetscFunctionBegin; 7433 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7434 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7435 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7436 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7437 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7438 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7439 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7440 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7441 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7442 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7443 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7444 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7445 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7446 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7447 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7448 /* Column indices */ 7449 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7450 maxFPoints = numCPoints; 7451 /* Compress out points not in the section */ 7452 /* TODO: Squeeze out points with 0 dof as well */ 7453 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7454 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7455 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7456 cpoints[q*2] = cpoints[p]; 7457 cpoints[q*2+1] = cpoints[p+1]; 7458 ++q; 7459 } 7460 } 7461 numCPoints = q; 7462 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7463 PetscInt fdof; 7464 7465 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7466 if (!dof) continue; 7467 for (f = 0; f < numFields; ++f) { 7468 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7469 coffsets[f+1] += fdof; 7470 } 7471 numCIndices += dof; 7472 } 7473 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7474 /* Row indices */ 7475 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7476 { 7477 DMPlexCellRefiner cr; 7478 ierr = DMPlexCellRefinerCreate(dmc, &cr);CHKERRQ(ierr); 7479 ierr = DMPlexCellRefinerGetAffineTransforms(cr, ct, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 7480 ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 7481 } 7482 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7483 for (r = 0, q = 0; r < numSubcells; ++r) { 7484 /* TODO Map from coarse to fine cells */ 7485 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7486 /* Compress out points not in the section */ 7487 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7488 for (p = 0; p < numFPoints*2; p += 2) { 7489 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7490 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7491 if (!dof) continue; 7492 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7493 if (s < q) continue; 7494 ftotpoints[q*2] = fpoints[p]; 7495 ftotpoints[q*2+1] = fpoints[p+1]; 7496 ++q; 7497 } 7498 } 7499 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7500 } 7501 numFPoints = q; 7502 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7503 PetscInt fdof; 7504 7505 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7506 if (!dof) continue; 7507 for (f = 0; f < numFields; ++f) { 7508 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7509 foffsets[f+1] += fdof; 7510 } 7511 numFIndices += dof; 7512 } 7513 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7514 7515 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7516 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7517 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7518 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7519 if (numFields) { 7520 const PetscInt **permsF[32] = {NULL}; 7521 const PetscInt **permsC[32] = {NULL}; 7522 7523 for (f = 0; f < numFields; f++) { 7524 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7525 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7526 } 7527 for (p = 0; p < numFPoints; p++) { 7528 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7529 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7530 } 7531 for (p = 0; p < numCPoints; p++) { 7532 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7533 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7534 } 7535 for (f = 0; f < numFields; f++) { 7536 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7537 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7538 } 7539 } else { 7540 const PetscInt **permsF = NULL; 7541 const PetscInt **permsC = NULL; 7542 7543 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7544 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7545 for (p = 0, off = 0; p < numFPoints; p++) { 7546 const PetscInt *perm = permsF ? permsF[p] : NULL; 7547 7548 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7549 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7550 } 7551 for (p = 0, off = 0; p < numCPoints; p++) { 7552 const PetscInt *perm = permsC ? permsC[p] : NULL; 7553 7554 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7555 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7556 } 7557 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7558 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7559 } 7560 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 7561 /* TODO: flips */ 7562 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7563 if (ierr) { 7564 PetscMPIInt rank; 7565 PetscErrorCode ierr2; 7566 7567 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7568 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7569 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 7570 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 7571 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 7572 CHKERRQ(ierr); 7573 } 7574 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7575 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7576 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7577 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7578 PetscFunctionReturn(0); 7579 } 7580 7581 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 7582 { 7583 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7584 PetscInt *cpoints = NULL; 7585 PetscInt foffsets[32], coffsets[32]; 7586 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7587 DMPolytopeType ct; 7588 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7589 PetscErrorCode ierr; 7590 7591 PetscFunctionBegin; 7592 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7593 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7594 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7595 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7596 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7597 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7598 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7599 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7600 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7601 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7602 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7603 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7604 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7605 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7606 /* Column indices */ 7607 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7608 maxFPoints = numCPoints; 7609 /* Compress out points not in the section */ 7610 /* TODO: Squeeze out points with 0 dof as well */ 7611 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7612 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7613 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7614 cpoints[q*2] = cpoints[p]; 7615 cpoints[q*2+1] = cpoints[p+1]; 7616 ++q; 7617 } 7618 } 7619 numCPoints = q; 7620 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7621 PetscInt fdof; 7622 7623 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7624 if (!dof) continue; 7625 for (f = 0; f < numFields; ++f) { 7626 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7627 coffsets[f+1] += fdof; 7628 } 7629 numCIndices += dof; 7630 } 7631 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7632 /* Row indices */ 7633 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7634 { 7635 DMPlexCellRefiner cr; 7636 ierr = DMPlexCellRefinerCreate(dmc, &cr);CHKERRQ(ierr); 7637 ierr = DMPlexCellRefinerGetAffineTransforms(cr, ct, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 7638 ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 7639 } 7640 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7641 for (r = 0, q = 0; r < numSubcells; ++r) { 7642 /* TODO Map from coarse to fine cells */ 7643 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7644 /* Compress out points not in the section */ 7645 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7646 for (p = 0; p < numFPoints*2; p += 2) { 7647 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7648 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7649 if (!dof) continue; 7650 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7651 if (s < q) continue; 7652 ftotpoints[q*2] = fpoints[p]; 7653 ftotpoints[q*2+1] = fpoints[p+1]; 7654 ++q; 7655 } 7656 } 7657 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7658 } 7659 numFPoints = q; 7660 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7661 PetscInt fdof; 7662 7663 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7664 if (!dof) continue; 7665 for (f = 0; f < numFields; ++f) { 7666 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7667 foffsets[f+1] += fdof; 7668 } 7669 numFIndices += dof; 7670 } 7671 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7672 7673 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7674 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7675 if (numFields) { 7676 const PetscInt **permsF[32] = {NULL}; 7677 const PetscInt **permsC[32] = {NULL}; 7678 7679 for (f = 0; f < numFields; f++) { 7680 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7681 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7682 } 7683 for (p = 0; p < numFPoints; p++) { 7684 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7685 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7686 } 7687 for (p = 0; p < numCPoints; p++) { 7688 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7689 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7690 } 7691 for (f = 0; f < numFields; f++) { 7692 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7693 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7694 } 7695 } else { 7696 const PetscInt **permsF = NULL; 7697 const PetscInt **permsC = NULL; 7698 7699 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7700 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7701 for (p = 0, off = 0; p < numFPoints; p++) { 7702 const PetscInt *perm = permsF ? permsF[p] : NULL; 7703 7704 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7705 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7706 } 7707 for (p = 0, off = 0; p < numCPoints; p++) { 7708 const PetscInt *perm = permsC ? permsC[p] : NULL; 7709 7710 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7711 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7712 } 7713 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7714 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7715 } 7716 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7717 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7718 PetscFunctionReturn(0); 7719 } 7720 7721 /*@C 7722 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 7723 7724 Input Parameter: 7725 . dm - The DMPlex object 7726 7727 Output Parameter: 7728 . cellHeight - The height of a cell 7729 7730 Level: developer 7731 7732 .seealso DMPlexSetVTKCellHeight() 7733 @*/ 7734 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7735 { 7736 DM_Plex *mesh = (DM_Plex*) dm->data; 7737 7738 PetscFunctionBegin; 7739 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7740 PetscValidPointer(cellHeight, 2); 7741 *cellHeight = mesh->vtkCellHeight; 7742 PetscFunctionReturn(0); 7743 } 7744 7745 /*@C 7746 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 7747 7748 Input Parameters: 7749 + dm - The DMPlex object 7750 - cellHeight - The height of a cell 7751 7752 Level: developer 7753 7754 .seealso DMPlexGetVTKCellHeight() 7755 @*/ 7756 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7757 { 7758 DM_Plex *mesh = (DM_Plex*) dm->data; 7759 7760 PetscFunctionBegin; 7761 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7762 mesh->vtkCellHeight = cellHeight; 7763 PetscFunctionReturn(0); 7764 } 7765 7766 /*@ 7767 DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 7768 7769 Input Parameter: 7770 . dm - The DMPlex object 7771 7772 Output Parameters: 7773 + gcStart - The first ghost cell, or NULL 7774 - gcEnd - The upper bound on ghost cells, or NULL 7775 7776 Level: advanced 7777 7778 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 7779 @*/ 7780 PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 7781 { 7782 DMLabel ctLabel; 7783 PetscErrorCode ierr; 7784 7785 PetscFunctionBegin; 7786 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7787 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 7788 ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr); 7789 PetscFunctionReturn(0); 7790 } 7791 7792 /* We can easily have a form that takes an IS instead */ 7793 PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 7794 { 7795 PetscSection section, globalSection; 7796 PetscInt *numbers, p; 7797 PetscErrorCode ierr; 7798 7799 PetscFunctionBegin; 7800 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7801 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 7802 for (p = pStart; p < pEnd; ++p) { 7803 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 7804 } 7805 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 7806 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7807 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 7808 for (p = pStart; p < pEnd; ++p) { 7809 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 7810 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 7811 else numbers[p-pStart] += shift; 7812 } 7813 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 7814 if (globalSize) { 7815 PetscLayout layout; 7816 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 7817 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 7818 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 7819 } 7820 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7821 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 7822 PetscFunctionReturn(0); 7823 } 7824 7825 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 7826 { 7827 PetscInt cellHeight, cStart, cEnd; 7828 PetscErrorCode ierr; 7829 7830 PetscFunctionBegin; 7831 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 7832 if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 7833 else {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 7834 ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 7835 PetscFunctionReturn(0); 7836 } 7837 7838 /*@ 7839 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 7840 7841 Input Parameter: 7842 . dm - The DMPlex object 7843 7844 Output Parameter: 7845 . globalCellNumbers - Global cell numbers for all cells on this process 7846 7847 Level: developer 7848 7849 .seealso DMPlexGetVertexNumbering() 7850 @*/ 7851 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 7852 { 7853 DM_Plex *mesh = (DM_Plex*) dm->data; 7854 PetscErrorCode ierr; 7855 7856 PetscFunctionBegin; 7857 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7858 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 7859 *globalCellNumbers = mesh->globalCellNumbers; 7860 PetscFunctionReturn(0); 7861 } 7862 7863 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 7864 { 7865 PetscInt vStart, vEnd; 7866 PetscErrorCode ierr; 7867 7868 PetscFunctionBegin; 7869 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7870 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7871 ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 7872 PetscFunctionReturn(0); 7873 } 7874 7875 /*@ 7876 DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 7877 7878 Input Parameter: 7879 . dm - The DMPlex object 7880 7881 Output Parameter: 7882 . globalVertexNumbers - Global vertex numbers for all vertices on this process 7883 7884 Level: developer 7885 7886 .seealso DMPlexGetCellNumbering() 7887 @*/ 7888 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 7889 { 7890 DM_Plex *mesh = (DM_Plex*) dm->data; 7891 PetscErrorCode ierr; 7892 7893 PetscFunctionBegin; 7894 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7895 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 7896 *globalVertexNumbers = mesh->globalVertexNumbers; 7897 PetscFunctionReturn(0); 7898 } 7899 7900 /*@ 7901 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 7902 7903 Input Parameter: 7904 . dm - The DMPlex object 7905 7906 Output Parameter: 7907 . globalPointNumbers - Global numbers for all points on this process 7908 7909 Level: developer 7910 7911 .seealso DMPlexGetCellNumbering() 7912 @*/ 7913 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 7914 { 7915 IS nums[4]; 7916 PetscInt depths[4], gdepths[4], starts[4]; 7917 PetscInt depth, d, shift = 0; 7918 PetscErrorCode ierr; 7919 7920 PetscFunctionBegin; 7921 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7922 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7923 /* For unstratified meshes use dim instead of depth */ 7924 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 7925 for (d = 0; d <= depth; ++d) { 7926 PetscInt end; 7927 7928 depths[d] = depth-d; 7929 ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 7930 if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 7931 } 7932 ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 7933 ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 7934 for (d = 0; d <= depth; ++d) { 7935 if (starts[d] >= 0 && depths[d] != gdepths[d]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 7936 } 7937 for (d = 0; d <= depth; ++d) { 7938 PetscInt pStart, pEnd, gsize; 7939 7940 ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 7941 ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 7942 shift += gsize; 7943 } 7944 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 7945 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 7946 PetscFunctionReturn(0); 7947 } 7948 7949 /*@ 7950 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 7951 7952 Input Parameter: 7953 . dm - The DMPlex object 7954 7955 Output Parameter: 7956 . ranks - The rank field 7957 7958 Options Database Keys: 7959 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 7960 7961 Level: intermediate 7962 7963 .seealso: DMView() 7964 @*/ 7965 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 7966 { 7967 DM rdm; 7968 PetscFE fe; 7969 PetscScalar *r; 7970 PetscMPIInt rank; 7971 DMPolytopeType ct; 7972 PetscInt dim, cStart, cEnd, c; 7973 PetscBool simplex; 7974 PetscErrorCode ierr; 7975 7976 PetscFunctionBeginUser; 7977 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7978 PetscValidPointer(ranks, 2); 7979 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 7980 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 7981 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 7982 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7983 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 7984 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 7985 ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 7986 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 7987 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 7988 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 7989 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 7990 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 7991 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 7992 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 7993 for (c = cStart; c < cEnd; ++c) { 7994 PetscScalar *lr; 7995 7996 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 7997 if (lr) *lr = rank; 7998 } 7999 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 8000 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8001 PetscFunctionReturn(0); 8002 } 8003 8004 /*@ 8005 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 8006 8007 Input Parameters: 8008 + dm - The DMPlex 8009 - label - The DMLabel 8010 8011 Output Parameter: 8012 . val - The label value field 8013 8014 Options Database Keys: 8015 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 8016 8017 Level: intermediate 8018 8019 .seealso: DMView() 8020 @*/ 8021 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8022 { 8023 DM rdm; 8024 PetscFE fe; 8025 PetscScalar *v; 8026 PetscInt dim, cStart, cEnd, c; 8027 PetscErrorCode ierr; 8028 8029 PetscFunctionBeginUser; 8030 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8031 PetscValidPointer(label, 2); 8032 PetscValidPointer(val, 3); 8033 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8034 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8035 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 8036 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 8037 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8038 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8039 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8040 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8041 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 8042 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 8043 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 8044 for (c = cStart; c < cEnd; ++c) { 8045 PetscScalar *lv; 8046 PetscInt cval; 8047 8048 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 8049 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 8050 *lv = cval; 8051 } 8052 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 8053 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8054 PetscFunctionReturn(0); 8055 } 8056 8057 /*@ 8058 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8059 8060 Input Parameter: 8061 . dm - The DMPlex object 8062 8063 Notes: 8064 This is a useful diagnostic when creating meshes programmatically. 8065 8066 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8067 8068 Level: developer 8069 8070 .seealso: DMCreate(), DMSetFromOptions() 8071 @*/ 8072 PetscErrorCode DMPlexCheckSymmetry(DM dm) 8073 { 8074 PetscSection coneSection, supportSection; 8075 const PetscInt *cone, *support; 8076 PetscInt coneSize, c, supportSize, s; 8077 PetscInt pStart, pEnd, p, pp, csize, ssize; 8078 PetscBool storagecheck = PETSC_TRUE; 8079 PetscErrorCode ierr; 8080 8081 PetscFunctionBegin; 8082 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8083 ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr); 8084 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 8085 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 8086 /* Check that point p is found in the support of its cone points, and vice versa */ 8087 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8088 for (p = pStart; p < pEnd; ++p) { 8089 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8090 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8091 for (c = 0; c < coneSize; ++c) { 8092 PetscBool dup = PETSC_FALSE; 8093 PetscInt d; 8094 for (d = c-1; d >= 0; --d) { 8095 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 8096 } 8097 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 8098 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 8099 for (s = 0; s < supportSize; ++s) { 8100 if (support[s] == p) break; 8101 } 8102 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 8103 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 8104 for (s = 0; s < coneSize; ++s) { 8105 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 8106 } 8107 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8108 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 8109 for (s = 0; s < supportSize; ++s) { 8110 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 8111 } 8112 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8113 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 8114 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 8115 } 8116 } 8117 ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 8118 if (p != pp) { storagecheck = PETSC_FALSE; continue; } 8119 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 8120 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 8121 for (s = 0; s < supportSize; ++s) { 8122 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 8123 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 8124 for (c = 0; c < coneSize; ++c) { 8125 ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 8126 if (cone[c] != pp) { c = 0; break; } 8127 if (cone[c] == p) break; 8128 } 8129 if (c >= coneSize) { 8130 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 8131 for (c = 0; c < supportSize; ++c) { 8132 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 8133 } 8134 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8135 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 8136 for (c = 0; c < coneSize; ++c) { 8137 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 8138 } 8139 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8140 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 8141 } 8142 } 8143 } 8144 if (storagecheck) { 8145 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 8146 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 8147 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 8148 } 8149 PetscFunctionReturn(0); 8150 } 8151 8152 /* 8153 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. 8154 */ 8155 static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8156 { 8157 DMPolytopeType cct; 8158 PetscInt ptpoints[4]; 8159 const PetscInt *cone, *ccone, *ptcone; 8160 PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8161 PetscErrorCode ierr; 8162 8163 PetscFunctionBegin; 8164 *unsplit = 0; 8165 switch (ct) { 8166 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8167 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8168 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8169 for (cp = 0; cp < coneSize; ++cp) { 8170 ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr); 8171 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8172 } 8173 break; 8174 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8175 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8176 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8177 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8178 for (cp = 0; cp < coneSize; ++cp) { 8179 ierr = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr); 8180 ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr); 8181 for (ccp = 0; ccp < cconeSize; ++ccp) { 8182 ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr); 8183 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8184 PetscInt p; 8185 for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8186 if (p == npt) ptpoints[npt++] = ccone[ccp]; 8187 } 8188 } 8189 } 8190 break; 8191 default: break; 8192 } 8193 for (pt = 0; pt < npt; ++pt) { 8194 ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr); 8195 if (ptcone[0] == ptcone[1]) ++(*unsplit); 8196 } 8197 PetscFunctionReturn(0); 8198 } 8199 8200 /*@ 8201 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8202 8203 Input Parameters: 8204 + dm - The DMPlex object 8205 - cellHeight - Normally 0 8206 8207 Notes: 8208 This is a useful diagnostic when creating meshes programmatically. 8209 Currently applicable only to homogeneous simplex or tensor meshes. 8210 8211 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8212 8213 Level: developer 8214 8215 .seealso: DMCreate(), DMSetFromOptions() 8216 @*/ 8217 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8218 { 8219 DMPlexInterpolatedFlag interp; 8220 DMPolytopeType ct; 8221 PetscInt vStart, vEnd, cStart, cEnd, c; 8222 PetscErrorCode ierr; 8223 8224 PetscFunctionBegin; 8225 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8226 ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr); 8227 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8228 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8229 for (c = cStart; c < cEnd; ++c) { 8230 PetscInt *closure = NULL; 8231 PetscInt coneSize, closureSize, cl, Nv = 0; 8232 8233 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8234 if ((PetscInt) ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c); 8235 if (ct == DM_POLYTOPE_UNKNOWN) continue; 8236 if (interp == DMPLEX_INTERPOLATED_FULL) { 8237 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8238 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)); 8239 } 8240 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8241 for (cl = 0; cl < closureSize*2; cl += 2) { 8242 const PetscInt p = closure[cl]; 8243 if ((p >= vStart) && (p < vEnd)) ++Nv; 8244 } 8245 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8246 /* Special Case: Tensor faces with identified vertices */ 8247 if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8248 PetscInt unsplit; 8249 8250 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8251 if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 8252 } 8253 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)); 8254 } 8255 PetscFunctionReturn(0); 8256 } 8257 8258 /*@ 8259 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 8260 8261 Not Collective 8262 8263 Input Parameters: 8264 + dm - The DMPlex object 8265 - cellHeight - Normally 0 8266 8267 Notes: 8268 This is a useful diagnostic when creating meshes programmatically. 8269 This routine is only relevant for meshes that are fully interpolated across all ranks. 8270 It will error out if a partially interpolated mesh is given on some rank. 8271 It will do nothing for locally uninterpolated mesh (as there is nothing to check). 8272 8273 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8274 8275 Level: developer 8276 8277 .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 8278 @*/ 8279 PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 8280 { 8281 PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8282 PetscErrorCode ierr; 8283 DMPlexInterpolatedFlag interpEnum; 8284 8285 PetscFunctionBegin; 8286 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8287 ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr); 8288 if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 8289 if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 8290 PetscMPIInt rank; 8291 MPI_Comm comm; 8292 8293 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8294 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8295 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 8296 } 8297 8298 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8299 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8300 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8301 for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 8302 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 8303 for (c = cStart; c < cEnd; ++c) { 8304 const PetscInt *cone, *ornt, *faceSizes, *faces; 8305 const DMPolytopeType *faceTypes; 8306 DMPolytopeType ct; 8307 PetscInt numFaces, coneSize, f; 8308 PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 8309 8310 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8311 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8312 if (unsplit) continue; 8313 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8314 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8315 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 8316 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8317 for (cl = 0; cl < closureSize*2; cl += 2) { 8318 const PetscInt p = closure[cl]; 8319 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 8320 } 8321 ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8322 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); 8323 for (f = 0; f < numFaces; ++f) { 8324 DMPolytopeType fct; 8325 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 8326 8327 ierr = DMPlexGetCellType(dm, cone[f], &fct);CHKERRQ(ierr); 8328 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8329 for (cl = 0; cl < fclosureSize*2; cl += 2) { 8330 const PetscInt p = fclosure[cl]; 8331 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 8332 } 8333 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]); 8334 for (v = 0; v < fnumCorners; ++v) { 8335 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]); 8336 } 8337 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8338 fOff += faceSizes[f]; 8339 } 8340 ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8341 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8342 } 8343 } 8344 PetscFunctionReturn(0); 8345 } 8346 8347 /*@ 8348 DMPlexCheckGeometry - Check the geometry of mesh cells 8349 8350 Input Parameter: 8351 . dm - The DMPlex object 8352 8353 Notes: 8354 This is a useful diagnostic when creating meshes programmatically. 8355 8356 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8357 8358 Level: developer 8359 8360 .seealso: DMCreate(), DMSetFromOptions() 8361 @*/ 8362 PetscErrorCode DMPlexCheckGeometry(DM dm) 8363 { 8364 Vec coordinates; 8365 PetscReal detJ, J[9], refVol = 1.0; 8366 PetscReal vol; 8367 PetscBool periodic; 8368 PetscInt dim, depth, dE, d, cStart, cEnd, c; 8369 PetscErrorCode ierr; 8370 8371 PetscFunctionBegin; 8372 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8373 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 8374 if (dim != dE) PetscFunctionReturn(0); 8375 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8376 ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr); 8377 for (d = 0; d < dim; ++d) refVol *= 2.0; 8378 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8379 /* Make sure local coordinates are created, because that step is collective */ 8380 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8381 for (c = cStart; c < cEnd; ++c) { 8382 DMPolytopeType ct; 8383 PetscInt unsplit; 8384 PetscBool ignoreZeroVol = PETSC_FALSE; 8385 8386 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8387 switch (ct) { 8388 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8389 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8390 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8391 ignoreZeroVol = PETSC_TRUE; break; 8392 default: break; 8393 } 8394 switch (ct) { 8395 case DM_POLYTOPE_TRI_PRISM: 8396 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8397 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8398 case DM_POLYTOPE_PYRAMID: 8399 continue; 8400 default: break; 8401 } 8402 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8403 if (unsplit) continue; 8404 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 8405 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); 8406 ierr = PetscInfo2(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 8407 if (depth > 1 && !periodic) { 8408 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 8409 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); 8410 ierr = PetscInfo2(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 8411 } 8412 } 8413 PetscFunctionReturn(0); 8414 } 8415 8416 /*@ 8417 DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 8418 8419 Input Parameters: 8420 . dm - The DMPlex object 8421 8422 Notes: 8423 This is mainly intended for debugging/testing purposes. 8424 It currently checks only meshes with no partition overlapping. 8425 8426 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8427 8428 Level: developer 8429 8430 .seealso: DMGetPointSF(), DMSetFromOptions() 8431 @*/ 8432 PetscErrorCode DMPlexCheckPointSF(DM dm) 8433 { 8434 PetscSF pointSF; 8435 PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 8436 const PetscInt *locals, *rootdegree; 8437 PetscBool distributed; 8438 PetscErrorCode ierr; 8439 8440 PetscFunctionBegin; 8441 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8442 ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr); 8443 ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 8444 if (!distributed) PetscFunctionReturn(0); 8445 ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 8446 if (overlap) { 8447 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping");CHKERRQ(ierr); 8448 PetscFunctionReturn(0); 8449 } 8450 if (!pointSF) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 8451 ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr); 8452 if (nroots < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 8453 ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 8454 ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 8455 8456 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 8457 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8458 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8459 for (l = 0; l < nleaves; ++l) { 8460 const PetscInt point = locals[l]; 8461 8462 if (point >= cStart && point < cEnd) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 8463 } 8464 8465 /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 8466 for (l = 0; l < nleaves; ++l) { 8467 const PetscInt point = locals[l]; 8468 const PetscInt *cone; 8469 PetscInt coneSize, c, idx; 8470 8471 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 8472 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 8473 for (c = 0; c < coneSize; ++c) { 8474 if (!rootdegree[cone[c]]) { 8475 ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr); 8476 if (idx < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 8477 } 8478 } 8479 } 8480 PetscFunctionReturn(0); 8481 } 8482 8483 typedef struct cell_stats 8484 { 8485 PetscReal min, max, sum, squaresum; 8486 PetscInt count; 8487 } cell_stats_t; 8488 8489 static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8490 { 8491 PetscInt i, N = *len; 8492 8493 for (i = 0; i < N; i++) { 8494 cell_stats_t *A = (cell_stats_t *) a; 8495 cell_stats_t *B = (cell_stats_t *) b; 8496 8497 B->min = PetscMin(A->min,B->min); 8498 B->max = PetscMax(A->max,B->max); 8499 B->sum += A->sum; 8500 B->squaresum += A->squaresum; 8501 B->count += A->count; 8502 } 8503 } 8504 8505 /*@ 8506 DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8507 8508 Collective on dm 8509 8510 Input Parameters: 8511 + dm - The DMPlex object 8512 . output - If true, statistics will be displayed on stdout 8513 - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8514 8515 Notes: 8516 This is mainly intended for debugging/testing purposes. 8517 8518 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8519 8520 Level: developer 8521 8522 .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality() 8523 @*/ 8524 PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8525 { 8526 DM dmCoarse; 8527 cell_stats_t stats, globalStats; 8528 MPI_Comm comm = PetscObjectComm((PetscObject)dm); 8529 PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 8530 PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8531 PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 8532 PetscMPIInt rank,size; 8533 PetscErrorCode ierr; 8534 8535 PetscFunctionBegin; 8536 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8537 stats.min = PETSC_MAX_REAL; 8538 stats.max = PETSC_MIN_REAL; 8539 stats.sum = stats.squaresum = 0.; 8540 stats.count = 0; 8541 8542 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 8543 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8544 ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr); 8545 ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr); 8546 ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 8547 ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); 8548 for (c = cStart; c < cEnd; c++) { 8549 PetscInt i; 8550 PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8551 8552 ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 8553 if (detJ < 0.0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 8554 for (i = 0; i < PetscSqr(cdim); ++i) { 8555 frobJ += J[i] * J[i]; 8556 frobInvJ += invJ[i] * invJ[i]; 8557 } 8558 cond2 = frobJ * frobInvJ; 8559 cond = PetscSqrtReal(cond2); 8560 8561 stats.min = PetscMin(stats.min,cond); 8562 stats.max = PetscMax(stats.max,cond); 8563 stats.sum += cond; 8564 stats.squaresum += cond2; 8565 stats.count++; 8566 if (output && cond > limit) { 8567 PetscSection coordSection; 8568 Vec coordsLocal; 8569 PetscScalar *coords = NULL; 8570 PetscInt Nv, d, clSize, cl, *closure = NULL; 8571 8572 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8573 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8574 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8575 ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr); 8576 for (i = 0; i < Nv/cdim; ++i) { 8577 ierr = PetscSynchronizedPrintf(comm, " Vertex %D: (", i);CHKERRQ(ierr); 8578 for (d = 0; d < cdim; ++d) { 8579 if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);} 8580 ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr); 8581 } 8582 ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr); 8583 } 8584 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8585 for (cl = 0; cl < clSize*2; cl += 2) { 8586 const PetscInt edge = closure[cl]; 8587 8588 if ((edge >= eStart) && (edge < eEnd)) { 8589 PetscReal len; 8590 8591 ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr); 8592 ierr = PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr); 8593 } 8594 } 8595 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8596 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8597 } 8598 } 8599 if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 8600 8601 if (size > 1) { 8602 PetscMPIInt blockLengths[2] = {4,1}; 8603 MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8604 MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8605 MPI_Op statReduce; 8606 8607 ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRMPI(ierr); 8608 ierr = MPI_Type_commit(&statType);CHKERRMPI(ierr); 8609 ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRMPI(ierr); 8610 ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRMPI(ierr); 8611 ierr = MPI_Op_free(&statReduce);CHKERRMPI(ierr); 8612 ierr = MPI_Type_free(&statType);CHKERRMPI(ierr); 8613 } else { 8614 ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr); 8615 } 8616 if (!rank) { 8617 count = globalStats.count; 8618 min = globalStats.min; 8619 max = globalStats.max; 8620 mean = globalStats.sum / globalStats.count; 8621 stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8622 } 8623 8624 if (output) { 8625 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); 8626 } 8627 ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 8628 8629 ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 8630 if (dmCoarse) { 8631 PetscBool isplex; 8632 8633 ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 8634 if (isplex) { 8635 ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr); 8636 } 8637 } 8638 PetscFunctionReturn(0); 8639 } 8640 8641 /*@ 8642 DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8643 orthogonal quality below given tolerance. 8644 8645 Collective on dm 8646 8647 Input Parameters: 8648 + dm - The DMPlex object 8649 . fv - Optional PetscFV object for pre-computed cell/face centroid information 8650 - atol - [0, 1] Absolute tolerance for tagging cells. 8651 8652 Output Parameters: 8653 + OrthQual - Vec containing orthogonal quality per cell 8654 - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8655 8656 Options Database Keys: 8657 + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8658 supported. 8659 - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8660 8661 Notes: 8662 Orthogonal quality is given by the following formula: 8663 8664 \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8665 8666 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 8667 is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8668 current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8669 calculating the cosine of the angle between these vectors. 8670 8671 Orthogonal quality ranges from 1 (best) to 0 (worst). 8672 8673 This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8674 pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8675 8676 Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8677 8678 Level: intermediate 8679 8680 .seealso: DMPlexCheckCellShape(), DMCreateLabel() 8681 @*/ 8682 PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8683 { 8684 PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 8685 PetscInt *idx; 8686 PetscScalar *oqVals; 8687 const PetscScalar *cellGeomArr, *faceGeomArr; 8688 PetscReal *ci, *fi, *Ai; 8689 MPI_Comm comm; 8690 Vec cellgeom, facegeom; 8691 DM dmFace, dmCell; 8692 IS glob; 8693 ISLocalToGlobalMapping ltog; 8694 PetscViewer vwr; 8695 PetscErrorCode ierr; 8696 8697 PetscFunctionBegin; 8698 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8699 if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8700 PetscValidPointer(OrthQual, 4); 8701 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); 8702 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8703 ierr = DMGetDimension(dm, &nc);CHKERRQ(ierr); 8704 if (nc < 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc); 8705 { 8706 DMPlexInterpolatedFlag interpFlag; 8707 8708 ierr = DMPlexIsInterpolated(dm, &interpFlag);CHKERRQ(ierr); 8709 if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 8710 PetscMPIInt rank; 8711 8712 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8713 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 8714 } 8715 } 8716 if (OrthQualLabel) { 8717 PetscValidPointer(OrthQualLabel, 5); 8718 ierr = DMCreateLabel(dm, "Orthogonal_Quality");CHKERRQ(ierr); 8719 ierr = DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel);CHKERRQ(ierr); 8720 } else {*OrthQualLabel = NULL;} 8721 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8722 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8723 ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob);CHKERRQ(ierr); 8724 ierr = ISLocalToGlobalMappingCreateIS(glob, <og);CHKERRQ(ierr); 8725 ierr = ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 8726 ierr = VecCreate(comm, OrthQual);CHKERRQ(ierr); 8727 ierr = VecSetType(*OrthQual, VECSTANDARD);CHKERRQ(ierr); 8728 ierr = VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr); 8729 ierr = VecSetLocalToGlobalMapping(*OrthQual, ltog);CHKERRQ(ierr); 8730 ierr = VecSetUp(*OrthQual);CHKERRQ(ierr); 8731 ierr = ISDestroy(&glob);CHKERRQ(ierr); 8732 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 8733 ierr = DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL);CHKERRQ(ierr); 8734 ierr = VecGetArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8735 ierr = VecGetArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8736 ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr); 8737 ierr = VecGetDM(facegeom, &dmFace);CHKERRQ(ierr); 8738 ierr = PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai);CHKERRQ(ierr); 8739 for (cell = cStart; cell < cEnd; cellIter++,cell++) { 8740 PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 8741 PetscInt cellarr[2], *adj = NULL; 8742 PetscScalar *cArr, *fArr; 8743 PetscReal minvalc = 1.0, minvalf = 1.0; 8744 PetscFVCellGeom *cg; 8745 8746 idx[cellIter] = cell-cStart; 8747 cellarr[0] = cell; 8748 /* Make indexing into cellGeom easier */ 8749 ierr = DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg);CHKERRQ(ierr); 8750 ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj);CHKERRQ(ierr); 8751 /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 8752 ierr = PetscCalloc2(adjSize, &cArr, adjSize, &fArr);CHKERRQ(ierr); 8753 for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 8754 PetscInt i; 8755 const PetscInt neigh = adj[cellneigh]; 8756 PetscReal normci = 0, normfi = 0, normai = 0; 8757 PetscFVCellGeom *cgneigh; 8758 PetscFVFaceGeom *fg; 8759 8760 /* Don't count ourselves in the neighbor list */ 8761 if (neigh == cell) continue; 8762 ierr = DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh);CHKERRQ(ierr); 8763 cellarr[1] = neigh; 8764 { 8765 PetscInt numcovpts; 8766 const PetscInt *covpts; 8767 8768 ierr = DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 8769 ierr = DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg);CHKERRQ(ierr); 8770 ierr = DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 8771 } 8772 8773 /* Compute c_i, f_i and their norms */ 8774 for (i = 0; i < nc; i++) { 8775 ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 8776 fi[i] = fg->centroid[i] - cg->centroid[i]; 8777 Ai[i] = fg->normal[i]; 8778 normci += PetscPowReal(ci[i], 2); 8779 normfi += PetscPowReal(fi[i], 2); 8780 normai += PetscPowReal(Ai[i], 2); 8781 } 8782 normci = PetscSqrtReal(normci); 8783 normfi = PetscSqrtReal(normfi); 8784 normai = PetscSqrtReal(normai); 8785 8786 /* Normalize and compute for each face-cell-normal pair */ 8787 for (i = 0; i < nc; i++) { 8788 ci[i] = ci[i]/normci; 8789 fi[i] = fi[i]/normfi; 8790 Ai[i] = Ai[i]/normai; 8791 /* PetscAbs because I don't know if normals are guaranteed to point out */ 8792 cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 8793 fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 8794 } 8795 if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 8796 minvalc = PetscRealPart(cArr[cellneighiter]); 8797 } 8798 if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 8799 minvalf = PetscRealPart(fArr[cellneighiter]); 8800 } 8801 } 8802 ierr = PetscFree(adj);CHKERRQ(ierr); 8803 ierr = PetscFree2(cArr, fArr);CHKERRQ(ierr); 8804 /* Defer to cell if they're equal */ 8805 oqVals[cellIter] = PetscMin(minvalf, minvalc); 8806 if (OrthQualLabel) { 8807 if (PetscRealPart(oqVals[cellIter]) <= atol) {ierr = DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE);CHKERRQ(ierr);} 8808 } 8809 } 8810 ierr = VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES);CHKERRQ(ierr); 8811 ierr = VecAssemblyBegin(*OrthQual);CHKERRQ(ierr); 8812 ierr = VecAssemblyEnd(*OrthQual);CHKERRQ(ierr); 8813 ierr = VecRestoreArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8814 ierr = VecRestoreArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8815 ierr = PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL);CHKERRQ(ierr); 8816 if (OrthQualLabel) { 8817 if (vwr) {ierr = DMLabelView(*OrthQualLabel, vwr);CHKERRQ(ierr);} 8818 } 8819 ierr = PetscFree5(idx, oqVals, ci, fi, Ai);CHKERRQ(ierr); 8820 ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr); 8821 ierr = VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view");CHKERRQ(ierr); 8822 PetscFunctionReturn(0); 8823 } 8824 8825 /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 8826 * interpolator construction */ 8827 static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 8828 { 8829 PetscSection section, newSection, gsection; 8830 PetscSF sf; 8831 PetscBool hasConstraints, ghasConstraints; 8832 PetscErrorCode ierr; 8833 8834 PetscFunctionBegin; 8835 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8836 PetscValidPointer(odm,2); 8837 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 8838 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 8839 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 8840 if (!ghasConstraints) { 8841 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 8842 *odm = dm; 8843 PetscFunctionReturn(0); 8844 } 8845 ierr = DMClone(dm, odm);CHKERRQ(ierr); 8846 ierr = DMCopyFields(dm, *odm);CHKERRQ(ierr); 8847 ierr = DMGetLocalSection(*odm, &newSection);CHKERRQ(ierr); 8848 ierr = DMGetPointSF(*odm, &sf);CHKERRQ(ierr); 8849 ierr = PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 8850 ierr = DMSetGlobalSection(*odm, gsection);CHKERRQ(ierr); 8851 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 8852 PetscFunctionReturn(0); 8853 } 8854 8855 static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 8856 { 8857 DM dmco, dmfo; 8858 Mat interpo; 8859 Vec rscale; 8860 Vec cglobalo, clocal; 8861 Vec fglobal, fglobalo, flocal; 8862 PetscBool regular; 8863 PetscErrorCode ierr; 8864 8865 PetscFunctionBegin; 8866 ierr = DMGetFullDM(dmc, &dmco);CHKERRQ(ierr); 8867 ierr = DMGetFullDM(dmf, &dmfo);CHKERRQ(ierr); 8868 ierr = DMSetCoarseDM(dmfo, dmco);CHKERRQ(ierr); 8869 ierr = DMPlexGetRegularRefinement(dmf, ®ular);CHKERRQ(ierr); 8870 ierr = DMPlexSetRegularRefinement(dmfo, regular);CHKERRQ(ierr); 8871 ierr = DMCreateInterpolation(dmco, dmfo, &interpo, &rscale);CHKERRQ(ierr); 8872 ierr = DMCreateGlobalVector(dmco, &cglobalo);CHKERRQ(ierr); 8873 ierr = DMCreateLocalVector(dmc, &clocal);CHKERRQ(ierr); 8874 ierr = VecSet(cglobalo, 0.);CHKERRQ(ierr); 8875 ierr = VecSet(clocal, 0.);CHKERRQ(ierr); 8876 ierr = DMCreateGlobalVector(dmf, &fglobal);CHKERRQ(ierr); 8877 ierr = DMCreateGlobalVector(dmfo, &fglobalo);CHKERRQ(ierr); 8878 ierr = DMCreateLocalVector(dmf, &flocal);CHKERRQ(ierr); 8879 ierr = VecSet(fglobal, 0.);CHKERRQ(ierr); 8880 ierr = VecSet(fglobalo, 0.);CHKERRQ(ierr); 8881 ierr = VecSet(flocal, 0.);CHKERRQ(ierr); 8882 ierr = DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL);CHKERRQ(ierr); 8883 ierr = DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 8884 ierr = DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 8885 ierr = MatMult(interpo, cglobalo, fglobalo);CHKERRQ(ierr); 8886 ierr = DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 8887 ierr = DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 8888 ierr = DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 8889 ierr = DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 8890 *shift = fglobal; 8891 ierr = VecDestroy(&flocal);CHKERRQ(ierr); 8892 ierr = VecDestroy(&fglobalo);CHKERRQ(ierr); 8893 ierr = VecDestroy(&clocal);CHKERRQ(ierr); 8894 ierr = VecDestroy(&cglobalo);CHKERRQ(ierr); 8895 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 8896 ierr = MatDestroy(&interpo);CHKERRQ(ierr); 8897 ierr = DMDestroy(&dmfo);CHKERRQ(ierr); 8898 ierr = DMDestroy(&dmco);CHKERRQ(ierr); 8899 PetscFunctionReturn(0); 8900 } 8901 8902 PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 8903 { 8904 PetscObject shifto; 8905 Vec shift; 8906 8907 PetscErrorCode ierr; 8908 8909 PetscFunctionBegin; 8910 if (!interp) { 8911 Vec rscale; 8912 8913 ierr = DMCreateInterpolation(coarse, fine, &interp, &rscale);CHKERRQ(ierr); 8914 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 8915 } else { 8916 ierr = PetscObjectReference((PetscObject)interp);CHKERRQ(ierr); 8917 } 8918 ierr = PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto);CHKERRQ(ierr); 8919 if (!shifto) { 8920 ierr = DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift);CHKERRQ(ierr); 8921 ierr = PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift);CHKERRQ(ierr); 8922 shifto = (PetscObject) shift; 8923 ierr = VecDestroy(&shift);CHKERRQ(ierr); 8924 } 8925 shift = (Vec) shifto; 8926 ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr); 8927 ierr = VecAXPY(fineSol, 1.0, shift);CHKERRQ(ierr); 8928 ierr = MatDestroy(&interp);CHKERRQ(ierr); 8929 PetscFunctionReturn(0); 8930 } 8931 8932 /* Pointwise interpolation 8933 Just code FEM for now 8934 u^f = I u^c 8935 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 8936 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 8937 I_{ij} = psi^f_i phi^c_j 8938 */ 8939 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 8940 { 8941 PetscSection gsc, gsf; 8942 PetscInt m, n; 8943 void *ctx; 8944 DM cdm; 8945 PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 8946 PetscErrorCode ierr; 8947 8948 PetscFunctionBegin; 8949 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 8950 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 8951 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 8952 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 8953 8954 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 8955 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 8956 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 8957 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 8958 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 8959 8960 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 8961 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 8962 if (!isRefined || (regular && cdm == dmCoarse)) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx);CHKERRQ(ierr);} 8963 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 8964 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 8965 if (scaling) { 8966 /* Use naive scaling */ 8967 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 8968 } 8969 PetscFunctionReturn(0); 8970 } 8971 8972 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 8973 { 8974 PetscErrorCode ierr; 8975 VecScatter ctx; 8976 8977 PetscFunctionBegin; 8978 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 8979 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 8980 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 8981 PetscFunctionReturn(0); 8982 } 8983 8984 static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8985 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8986 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8987 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 8988 { 8989 g0[0] = 1.0; 8990 } 8991 8992 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 8993 { 8994 PetscSection gsc, gsf; 8995 PetscInt m, n; 8996 void *ctx; 8997 DM cdm; 8998 PetscBool regular; 8999 PetscErrorCode ierr; 9000 9001 PetscFunctionBegin; 9002 if (dmFine == dmCoarse) { 9003 DM dmc; 9004 PetscDS ds; 9005 Vec u; 9006 IS cellIS; 9007 PetscFormKey key; 9008 PetscInt depth; 9009 9010 ierr = DMClone(dmFine, &dmc);CHKERRQ(ierr); 9011 ierr = DMCopyDisc(dmFine, dmc);CHKERRQ(ierr); 9012 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9013 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9014 ierr = DMCreateMatrix(dmc, mass);CHKERRQ(ierr); 9015 ierr = DMGetGlobalVector(dmc, &u);CHKERRQ(ierr); 9016 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9017 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9018 ierr = MatZeroEntries(*mass);CHKERRQ(ierr); 9019 key.label = NULL; 9020 key.value = 0; 9021 key.field = 0; 9022 key.part = 0; 9023 ierr = DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL);CHKERRQ(ierr); 9024 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9025 ierr = DMRestoreGlobalVector(dmc, &u);CHKERRQ(ierr); 9026 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9027 } else { 9028 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9029 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9030 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9031 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9032 9033 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 9034 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9035 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 9036 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9037 9038 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9039 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9040 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9041 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9042 } 9043 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 9044 PetscFunctionReturn(0); 9045 } 9046 9047 /*@ 9048 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9049 9050 Input Parameter: 9051 . dm - The DMPlex object 9052 9053 Output Parameter: 9054 . regular - The flag 9055 9056 Level: intermediate 9057 9058 .seealso: DMPlexSetRegularRefinement() 9059 @*/ 9060 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 9061 { 9062 PetscFunctionBegin; 9063 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9064 PetscValidPointer(regular, 2); 9065 *regular = ((DM_Plex *) dm->data)->regularRefinement; 9066 PetscFunctionReturn(0); 9067 } 9068 9069 /*@ 9070 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9071 9072 Input Parameters: 9073 + dm - The DMPlex object 9074 - regular - The flag 9075 9076 Level: intermediate 9077 9078 .seealso: DMPlexGetRegularRefinement() 9079 @*/ 9080 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 9081 { 9082 PetscFunctionBegin; 9083 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9084 ((DM_Plex *) dm->data)->regularRefinement = regular; 9085 PetscFunctionReturn(0); 9086 } 9087 9088 /*@ 9089 DMPlexGetCellRefinerType - Get the strategy for refining a cell 9090 9091 Input Parameter: 9092 . dm - The DMPlex object 9093 9094 Output Parameter: 9095 . cr - The strategy number 9096 9097 Level: intermediate 9098 9099 .seealso: DMPlexSetCellRefinerType(), DMPlexSetRegularRefinement() 9100 @*/ 9101 PetscErrorCode DMPlexGetCellRefinerType(DM dm, DMPlexCellRefinerType *cr) 9102 { 9103 PetscFunctionBegin; 9104 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9105 PetscValidPointer(cr, 2); 9106 *cr = ((DM_Plex *) dm->data)->cellRefiner; 9107 PetscFunctionReturn(0); 9108 } 9109 9110 /*@ 9111 DMPlexSetCellRefinerType - Set the strategy for refining a cell 9112 9113 Input Parameters: 9114 + dm - The DMPlex object 9115 - cr - The strategy number 9116 9117 Level: intermediate 9118 9119 .seealso: DMPlexGetCellRefinerType(), DMPlexGetRegularRefinement() 9120 @*/ 9121 PetscErrorCode DMPlexSetCellRefinerType(DM dm, DMPlexCellRefinerType cr) 9122 { 9123 PetscFunctionBegin; 9124 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9125 ((DM_Plex *) dm->data)->cellRefiner = cr; 9126 PetscFunctionReturn(0); 9127 } 9128 9129 /* anchors */ 9130 /*@ 9131 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9132 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 9133 9134 not collective 9135 9136 Input Parameters: 9137 . dm - The DMPlex object 9138 9139 Output Parameters: 9140 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9141 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9142 9143 Level: intermediate 9144 9145 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 9146 @*/ 9147 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9148 { 9149 DM_Plex *plex = (DM_Plex *)dm->data; 9150 PetscErrorCode ierr; 9151 9152 PetscFunctionBegin; 9153 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9154 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 9155 if (anchorSection) *anchorSection = plex->anchorSection; 9156 if (anchorIS) *anchorIS = plex->anchorIS; 9157 PetscFunctionReturn(0); 9158 } 9159 9160 /*@ 9161 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9162 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9163 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9164 9165 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9166 DMGetConstraints() and filling in the entries in the constraint matrix. 9167 9168 collective on dm 9169 9170 Input Parameters: 9171 + dm - The DMPlex object 9172 . 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). 9173 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9174 9175 The reference counts of anchorSection and anchorIS are incremented. 9176 9177 Level: intermediate 9178 9179 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 9180 @*/ 9181 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9182 { 9183 DM_Plex *plex = (DM_Plex *)dm->data; 9184 PetscMPIInt result; 9185 PetscErrorCode ierr; 9186 9187 PetscFunctionBegin; 9188 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9189 if (anchorSection) { 9190 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 9191 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRMPI(ierr); 9192 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9193 } 9194 if (anchorIS) { 9195 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 9196 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRMPI(ierr); 9197 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9198 } 9199 9200 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 9201 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 9202 plex->anchorSection = anchorSection; 9203 9204 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 9205 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 9206 plex->anchorIS = anchorIS; 9207 9208 if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9209 PetscInt size, a, pStart, pEnd; 9210 const PetscInt *anchors; 9211 9212 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9213 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 9214 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 9215 for (a = 0; a < size; a++) { 9216 PetscInt p; 9217 9218 p = anchors[a]; 9219 if (p >= pStart && p < pEnd) { 9220 PetscInt dof; 9221 9222 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9223 if (dof) { 9224 PetscErrorCode ierr2; 9225 9226 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 9227 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 9228 } 9229 } 9230 } 9231 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 9232 } 9233 /* reset the generic constraints */ 9234 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 9235 PetscFunctionReturn(0); 9236 } 9237 9238 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9239 { 9240 PetscSection anchorSection; 9241 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9242 PetscErrorCode ierr; 9243 9244 PetscFunctionBegin; 9245 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9246 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9247 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 9248 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9249 if (numFields) { 9250 PetscInt f; 9251 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 9252 9253 for (f = 0; f < numFields; f++) { 9254 PetscInt numComp; 9255 9256 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 9257 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 9258 } 9259 } 9260 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9261 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9262 pStart = PetscMax(pStart,sStart); 9263 pEnd = PetscMin(pEnd,sEnd); 9264 pEnd = PetscMax(pStart,pEnd); 9265 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 9266 for (p = pStart; p < pEnd; p++) { 9267 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9268 if (dof) { 9269 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 9270 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 9271 for (f = 0; f < numFields; f++) { 9272 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 9273 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 9274 } 9275 } 9276 } 9277 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 9278 ierr = PetscObjectSetName((PetscObject) *cSec, "Constraint Section");CHKERRQ(ierr); 9279 PetscFunctionReturn(0); 9280 } 9281 9282 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9283 { 9284 PetscSection aSec; 9285 PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 9286 const PetscInt *anchors; 9287 PetscInt numFields, f; 9288 IS aIS; 9289 PetscErrorCode ierr; 9290 MatType mtype; 9291 PetscBool iscuda,iskokkos; 9292 9293 PetscFunctionBegin; 9294 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9295 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 9296 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 9297 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 9298 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 9299 ierr = PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr); 9300 if (!iscuda) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr); } 9301 ierr = PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos);CHKERRQ(ierr); 9302 if (!iskokkos) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos);CHKERRQ(ierr); } 9303 if (iscuda) mtype = MATSEQAIJCUSPARSE; 9304 else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9305 else mtype = MATSEQAIJ; 9306 ierr = MatSetType(*cMat,mtype);CHKERRQ(ierr); 9307 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 9308 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 9309 /* cSec will be a subset of aSec and section */ 9310 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 9311 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9312 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 9313 i[0] = 0; 9314 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9315 for (p = pStart; p < pEnd; p++) { 9316 PetscInt rDof, rOff, r; 9317 9318 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9319 if (!rDof) continue; 9320 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9321 if (numFields) { 9322 for (f = 0; f < numFields; f++) { 9323 annz = 0; 9324 for (r = 0; r < rDof; r++) { 9325 a = anchors[rOff + r]; 9326 if (a < sStart || a >= sEnd) continue; 9327 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9328 annz += aDof; 9329 } 9330 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9331 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 9332 for (q = 0; q < dof; q++) { 9333 i[off + q + 1] = i[off + q] + annz; 9334 } 9335 } 9336 } 9337 else { 9338 annz = 0; 9339 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9340 for (q = 0; q < dof; q++) { 9341 a = anchors[rOff + q]; 9342 if (a < sStart || a >= sEnd) continue; 9343 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9344 annz += aDof; 9345 } 9346 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9347 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 9348 for (q = 0; q < dof; q++) { 9349 i[off + q + 1] = i[off + q] + annz; 9350 } 9351 } 9352 } 9353 nnz = i[m]; 9354 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 9355 offset = 0; 9356 for (p = pStart; p < pEnd; p++) { 9357 if (numFields) { 9358 for (f = 0; f < numFields; f++) { 9359 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9360 for (q = 0; q < dof; q++) { 9361 PetscInt rDof, rOff, r; 9362 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9363 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9364 for (r = 0; r < rDof; r++) { 9365 PetscInt s; 9366 9367 a = anchors[rOff + r]; 9368 if (a < sStart || a >= sEnd) continue; 9369 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9370 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 9371 for (s = 0; s < aDof; s++) { 9372 j[offset++] = aOff + s; 9373 } 9374 } 9375 } 9376 } 9377 } 9378 else { 9379 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9380 for (q = 0; q < dof; q++) { 9381 PetscInt rDof, rOff, r; 9382 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9383 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9384 for (r = 0; r < rDof; r++) { 9385 PetscInt s; 9386 9387 a = anchors[rOff + r]; 9388 if (a < sStart || a >= sEnd) continue; 9389 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9390 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 9391 for (s = 0; s < aDof; s++) { 9392 j[offset++] = aOff + s; 9393 } 9394 } 9395 } 9396 } 9397 } 9398 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 9399 ierr = PetscFree(i);CHKERRQ(ierr); 9400 ierr = PetscFree(j);CHKERRQ(ierr); 9401 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 9402 PetscFunctionReturn(0); 9403 } 9404 9405 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 9406 { 9407 DM_Plex *plex = (DM_Plex *)dm->data; 9408 PetscSection anchorSection, section, cSec; 9409 Mat cMat; 9410 PetscErrorCode ierr; 9411 9412 PetscFunctionBegin; 9413 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9414 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9415 if (anchorSection) { 9416 PetscInt Nf; 9417 9418 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 9419 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 9420 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 9421 ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 9422 if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 9423 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 9424 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 9425 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 9426 } 9427 PetscFunctionReturn(0); 9428 } 9429 9430 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9431 { 9432 IS subis; 9433 PetscSection section, subsection; 9434 PetscErrorCode ierr; 9435 9436 PetscFunctionBegin; 9437 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9438 if (!section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 9439 if (!subdm) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9440 /* Create subdomain */ 9441 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 9442 /* Create submodel */ 9443 ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr); 9444 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 9445 ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr); 9446 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 9447 ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 9448 /* Create map from submodel to global model */ 9449 if (is) { 9450 PetscSection sectionGlobal, subsectionGlobal; 9451 IS spIS; 9452 const PetscInt *spmap; 9453 PetscInt *subIndices; 9454 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9455 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9456 9457 ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 9458 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 9459 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 9460 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 9461 ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 9462 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 9463 for (p = pStart; p < pEnd; ++p) { 9464 PetscInt gdof, pSubSize = 0; 9465 9466 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 9467 if (gdof > 0) { 9468 for (f = 0; f < Nf; ++f) { 9469 PetscInt fdof, fcdof; 9470 9471 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 9472 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 9473 pSubSize += fdof-fcdof; 9474 } 9475 subSize += pSubSize; 9476 if (pSubSize) { 9477 if (bs < 0) { 9478 bs = pSubSize; 9479 } else if (bs != pSubSize) { 9480 /* Layout does not admit a pointwise block size */ 9481 bs = 1; 9482 } 9483 } 9484 } 9485 } 9486 /* Must have same blocksize on all procs (some might have no points) */ 9487 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 9488 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 9489 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9490 else {bs = bsMinMax[0];} 9491 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 9492 for (p = pStart; p < pEnd; ++p) { 9493 PetscInt gdof, goff; 9494 9495 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 9496 if (gdof > 0) { 9497 const PetscInt point = spmap[p]; 9498 9499 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 9500 for (f = 0; f < Nf; ++f) { 9501 PetscInt fdof, fcdof, fc, f2, poff = 0; 9502 9503 /* Can get rid of this loop by storing field information in the global section */ 9504 for (f2 = 0; f2 < f; ++f2) { 9505 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 9506 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 9507 poff += fdof-fcdof; 9508 } 9509 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 9510 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 9511 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9512 subIndices[subOff] = goff+poff+fc; 9513 } 9514 } 9515 } 9516 } 9517 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 9518 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 9519 if (bs > 1) { 9520 /* We need to check that the block size does not come from non-contiguous fields */ 9521 PetscInt i, j, set = 1; 9522 for (i = 0; i < subSize; i += bs) { 9523 for (j = 0; j < bs; ++j) { 9524 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9525 } 9526 } 9527 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 9528 } 9529 /* Attach nullspace */ 9530 for (f = 0; f < Nf; ++f) { 9531 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9532 if ((*subdm)->nullspaceConstructors[f]) break; 9533 } 9534 if (f < Nf) { 9535 MatNullSpace nullSpace; 9536 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace);CHKERRQ(ierr); 9537 9538 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 9539 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 9540 } 9541 } 9542 PetscFunctionReturn(0); 9543 } 9544 9545 /*@ 9546 DMPlexMonitorThroughput - Report the cell throughput of FE integration 9547 9548 Input Parameter: 9549 - dm - The DM 9550 9551 Level: developer 9552 9553 Options Database Keys: 9554 . -dm_plex_monitor_throughput - Activate the monitor 9555 9556 .seealso: DMSetFromOptions(), DMPlexCreate() 9557 @*/ 9558 PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9559 { 9560 #if defined(PETSC_USE_LOG) 9561 PetscStageLog stageLog; 9562 PetscLogEvent event; 9563 PetscLogStage stage; 9564 PetscEventPerfInfo eventInfo; 9565 PetscReal cellRate, flopRate; 9566 PetscInt cStart, cEnd, Nf, N; 9567 const char *name; 9568 PetscErrorCode ierr; 9569 #endif 9570 9571 PetscFunctionBegin; 9572 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9573 #if defined(PETSC_USE_LOG) 9574 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 9575 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9576 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9577 ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 9578 ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr); 9579 ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr); 9580 ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr); 9581 N = (cEnd - cStart)*Nf*eventInfo.count; 9582 flopRate = eventInfo.flops/eventInfo.time; 9583 cellRate = N/eventInfo.time; 9584 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); 9585 #else 9586 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9587 #endif 9588 PetscFunctionReturn(0); 9589 } 9590