1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petsc/private/isimpl.h> 3 #include <petsc/private/vecimpl.h> 4 #include <petsc/private/glvisvecimpl.h> 5 #include <petscsf.h> 6 #include <petscds.h> 7 #include <petscdraw.h> 8 #include <petscdmfield.h> 9 10 /* Logging support */ 11 PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF,DMPLEX_LocatePoints; 12 13 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 14 15 /*@ 16 DMPlexIsSimplex - Is the first cell in this mesh a simplex? 17 18 Input Parameter: 19 . dm - The DMPlex object 20 21 Output Parameter: 22 . simplex - Flag checking for a simplex 23 24 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 25 If the mesh has no cells, this returns PETSC_FALSE. 26 27 Level: intermediate 28 29 .seealso DMPlexGetSimplexOrBoxCells(), DMPlexGetCellType(), DMPlexGetHeightStratum(), DMPolytopeTypeGetNumVertices() 30 @*/ 31 PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 32 { 33 DMPolytopeType ct; 34 PetscInt cStart, cEnd; 35 PetscErrorCode ierr; 36 37 PetscFunctionBegin; 38 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 39 if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);} 40 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 41 *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 42 PetscFunctionReturn(0); 43 } 44 45 /*@ 46 DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 47 48 Input Parameter: 49 + dm - The DMPlex object 50 - height - The cell height in the Plex, 0 is the default 51 52 Output Parameters: 53 + cStart - The first "normal" cell 54 - cEnd - The upper bound on "normal"" cells 55 56 Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 57 58 Level: developer 59 60 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 61 @*/ 62 PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 63 { 64 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 65 PetscInt cS, cE, c; 66 PetscErrorCode ierr; 67 68 PetscFunctionBegin; 69 ierr = DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE);CHKERRQ(ierr); 70 for (c = cS; c < cE; ++c) { 71 DMPolytopeType cct; 72 73 ierr = DMPlexGetCellType(dm, c, &cct);CHKERRQ(ierr); 74 if ((PetscInt) cct < 0) break; 75 switch (cct) { 76 case DM_POLYTOPE_POINT: 77 case DM_POLYTOPE_SEGMENT: 78 case DM_POLYTOPE_TRIANGLE: 79 case DM_POLYTOPE_QUADRILATERAL: 80 case DM_POLYTOPE_TETRAHEDRON: 81 case DM_POLYTOPE_HEXAHEDRON: 82 ct = cct; 83 break; 84 default: break; 85 } 86 if (ct != DM_POLYTOPE_UNKNOWN) break; 87 } 88 if (ct != DM_POLYTOPE_UNKNOWN) { 89 DMLabel ctLabel; 90 91 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 92 ierr = DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE);CHKERRQ(ierr); 93 } 94 if (cStart) *cStart = cS; 95 if (cEnd) *cEnd = cE; 96 PetscFunctionReturn(0); 97 } 98 99 PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 100 { 101 PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 102 PetscInt vcdof[2] = {0,0}, globalvcdof[2]; 103 PetscErrorCode ierr; 104 105 PetscFunctionBegin; 106 *ft = PETSC_VTK_INVALID; 107 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 108 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 109 ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 110 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 111 if (field >= 0) { 112 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]);CHKERRQ(ierr);} 113 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]);CHKERRQ(ierr);} 114 } else { 115 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vcdof[0]);CHKERRQ(ierr);} 116 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &vcdof[1]);CHKERRQ(ierr);} 117 } 118 ierr = MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 119 if (globalvcdof[0]) { 120 *sStart = vStart; 121 *sEnd = vEnd; 122 if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 123 else *ft = PETSC_VTK_POINT_FIELD; 124 } else if (globalvcdof[1]) { 125 *sStart = cStart; 126 *sEnd = cEnd; 127 if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 128 else *ft = PETSC_VTK_CELL_FIELD; 129 } else { 130 if (field >= 0) { 131 const char *fieldname; 132 133 ierr = PetscSectionGetFieldName(section, field, &fieldname);CHKERRQ(ierr); 134 ierr = PetscInfo2((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname);CHKERRQ(ierr); 135 } else { 136 ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\"%s\"\n");CHKERRQ(ierr); 137 } 138 } 139 PetscFunctionReturn(0); 140 } 141 142 static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 143 { 144 DM dm; 145 PetscSection s; 146 PetscDraw draw, popup; 147 DM cdm; 148 PetscSection coordSection; 149 Vec coordinates; 150 const PetscScalar *coords, *array; 151 PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 152 PetscReal vbound[2], time; 153 PetscBool isnull, flg; 154 PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 155 const char *name; 156 char title[PETSC_MAX_PATH_LEN]; 157 PetscErrorCode ierr; 158 159 PetscFunctionBegin; 160 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 161 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 162 if (isnull) PetscFunctionReturn(0); 163 164 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 165 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 166 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D. Use PETSCVIEWERGLVIS", dim); 167 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 168 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 169 ierr = DMGetCoarsenLevel(dm, &level);CHKERRQ(ierr); 170 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 171 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 172 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 173 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 174 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 175 176 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 177 ierr = DMGetOutputSequenceNumber(dm, &step, &time);CHKERRQ(ierr); 178 179 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 180 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 181 for (c = 0; c < N; c += dim) { 182 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 183 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 184 } 185 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 186 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 187 188 /* Could implement something like DMDASelectFields() */ 189 for (f = 0; f < Nf; ++f) { 190 DM fdm = dm; 191 Vec fv = v; 192 IS fis; 193 char prefix[PETSC_MAX_PATH_LEN]; 194 const char *fname; 195 196 ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr); 197 ierr = PetscSectionGetFieldName(s, f, &fname);CHKERRQ(ierr); 198 199 if (v->hdr.prefix) {ierr = PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix));CHKERRQ(ierr);} 200 else {prefix[0] = '\0';} 201 if (Nf > 1) { 202 ierr = DMCreateSubDM(dm, 1, &f, &fis, &fdm);CHKERRQ(ierr); 203 ierr = VecGetSubVector(v, fis, &fv);CHKERRQ(ierr); 204 ierr = PetscStrlcat(prefix, fname,sizeof(prefix));CHKERRQ(ierr); 205 ierr = PetscStrlcat(prefix, "_",sizeof(prefix));CHKERRQ(ierr); 206 } 207 for (comp = 0; comp < Nc; ++comp, ++w) { 208 PetscInt nmax = 2; 209 210 ierr = PetscViewerDrawGetDraw(viewer, w, &draw);CHKERRQ(ierr); 211 if (Nc > 1) {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time);CHKERRQ(ierr);} 212 else {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time);CHKERRQ(ierr);} 213 ierr = PetscDrawSetTitle(draw, title);CHKERRQ(ierr); 214 215 /* TODO Get max and min only for this component */ 216 ierr = PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg);CHKERRQ(ierr); 217 if (!flg) { 218 ierr = VecMin(fv, NULL, &vbound[0]);CHKERRQ(ierr); 219 ierr = VecMax(fv, NULL, &vbound[1]);CHKERRQ(ierr); 220 if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 221 } 222 ierr = PetscDrawGetPopup(draw, &popup);CHKERRQ(ierr); 223 ierr = PetscDrawScalePopup(popup, vbound[0], vbound[1]);CHKERRQ(ierr); 224 ierr = PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]);CHKERRQ(ierr); 225 226 ierr = VecGetArrayRead(fv, &array);CHKERRQ(ierr); 227 for (c = cStart; c < cEnd; ++c) { 228 PetscScalar *coords = NULL, *a = NULL; 229 PetscInt numCoords, color[4] = {-1,-1,-1,-1}; 230 231 ierr = DMPlexPointLocalRead(fdm, c, array, &a);CHKERRQ(ierr); 232 if (a) { 233 color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 234 color[1] = color[2] = color[3] = color[0]; 235 } else { 236 PetscScalar *vals = NULL; 237 PetscInt numVals, va; 238 239 ierr = DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 240 if (numVals % Nc) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %D does not divide the number of values in the closure %D", Nc, numVals); 241 switch (numVals/Nc) { 242 case 3: /* P1 Triangle */ 243 case 4: /* P1 Quadrangle */ 244 for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]); 245 break; 246 case 6: /* P2 Triangle */ 247 case 8: /* P2 Quadrangle */ 248 for (va = 0; va < numVals/(Nc*2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp + numVals/(Nc*2)]), vbound[0], vbound[1]); 249 break; 250 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc); 251 } 252 ierr = DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 253 } 254 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 255 switch (numCoords) { 256 case 6: 257 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 258 break; 259 case 8: 260 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 261 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0]);CHKERRQ(ierr); 262 break; 263 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords); 264 } 265 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 266 } 267 ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr); 268 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 269 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 270 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 271 } 272 if (Nf > 1) { 273 ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr); 274 ierr = ISDestroy(&fis);CHKERRQ(ierr); 275 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 276 } 277 } 278 PetscFunctionReturn(0); 279 } 280 281 static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 282 { 283 DM dm; 284 Vec locv; 285 const char *name; 286 PetscSection section; 287 PetscInt pStart, pEnd; 288 PetscInt numFields; 289 PetscViewerVTKFieldType ft; 290 PetscErrorCode ierr; 291 292 PetscFunctionBegin; 293 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 294 ierr = DMCreateLocalVector(dm, &locv);CHKERRQ(ierr); /* VTK viewer requires exclusive ownership of the vector */ 295 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 296 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 297 ierr = VecCopy(v, locv);CHKERRQ(ierr); 298 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 299 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 300 if (!numFields) { 301 ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 302 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 303 } else { 304 PetscInt f; 305 306 for (f = 0; f < numFields; f++) { 307 ierr = DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft);CHKERRQ(ierr); 308 if (ft == PETSC_VTK_INVALID) continue; 309 ierr = PetscObjectReference((PetscObject)locv);CHKERRQ(ierr); 310 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 311 } 312 ierr = VecDestroy(&locv);CHKERRQ(ierr); 313 } 314 PetscFunctionReturn(0); 315 } 316 317 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 318 { 319 DM dm; 320 PetscBool isvtk, ishdf5, isdraw, isglvis; 321 PetscErrorCode ierr; 322 323 PetscFunctionBegin; 324 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 325 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 326 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 327 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 328 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 329 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 330 if (isvtk || ishdf5 || isdraw || isglvis) { 331 PetscInt i,numFields; 332 PetscObject fe; 333 PetscBool fem = PETSC_FALSE; 334 Vec locv = v; 335 const char *name; 336 PetscInt step; 337 PetscReal time; 338 339 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 340 for (i=0; i<numFields; i++) { 341 ierr = DMGetField(dm, i, NULL, &fe);CHKERRQ(ierr); 342 if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; } 343 } 344 if (fem) { 345 PetscObject isZero; 346 347 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 348 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 349 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 350 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 351 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 352 ierr = VecCopy(v, locv);CHKERRQ(ierr); 353 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 354 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr); 355 } 356 if (isvtk) { 357 ierr = VecView_Plex_Local_VTK(locv, viewer);CHKERRQ(ierr); 358 } else if (ishdf5) { 359 #if defined(PETSC_HAVE_HDF5) 360 ierr = VecView_Plex_Local_HDF5_Internal(locv, viewer);CHKERRQ(ierr); 361 #else 362 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 363 #endif 364 } else if (isdraw) { 365 ierr = VecView_Plex_Local_Draw(locv, viewer);CHKERRQ(ierr); 366 } else if (isglvis) { 367 ierr = DMGetOutputSequenceNumber(dm, &step, NULL);CHKERRQ(ierr); 368 ierr = PetscViewerGLVisSetSnapId(viewer, step);CHKERRQ(ierr); 369 ierr = VecView_GLVis(locv, viewer);CHKERRQ(ierr); 370 } 371 if (fem) { 372 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 373 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 374 } 375 } else { 376 PetscBool isseq; 377 378 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 379 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 380 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 381 } 382 PetscFunctionReturn(0); 383 } 384 385 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 386 { 387 DM dm; 388 PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii; 389 PetscErrorCode ierr; 390 391 PetscFunctionBegin; 392 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 393 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 394 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 395 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 396 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 397 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 398 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 399 if (isvtk || isdraw || isglvis) { 400 Vec locv; 401 PetscObject isZero; 402 const char *name; 403 404 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 405 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 406 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 407 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 408 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 409 ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr); 410 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr); 411 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 412 ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr); 413 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 414 } else if (ishdf5) { 415 #if defined(PETSC_HAVE_HDF5) 416 ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 417 #else 418 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 419 #endif 420 } else if (isexodusii) { 421 #if defined(PETSC_HAVE_EXODUSII) 422 ierr = VecView_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 423 #else 424 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 425 #endif 426 } else { 427 PetscBool isseq; 428 429 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 430 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 431 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 432 } 433 PetscFunctionReturn(0); 434 } 435 436 PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 437 { 438 DM dm; 439 MPI_Comm comm; 440 PetscViewerFormat format; 441 Vec v; 442 PetscBool isvtk, ishdf5; 443 PetscErrorCode ierr; 444 445 PetscFunctionBegin; 446 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 447 ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 448 if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 449 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 450 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 451 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 452 if (format == PETSC_VIEWER_NATIVE) { 453 /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 454 /* this need a better fix */ 455 if (dm->useNatural) { 456 if (dm->sfNatural) { 457 const char *vecname; 458 PetscInt n, nroots; 459 460 ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr); 461 ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 462 if (n == nroots) { 463 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 464 ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 465 ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 466 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 467 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 468 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 469 } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 470 } else v = originalv; 471 } else v = originalv; 472 473 if (ishdf5) { 474 #if defined(PETSC_HAVE_HDF5) 475 ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 476 #else 477 SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 478 #endif 479 } else if (isvtk) { 480 SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 481 } else { 482 PetscBool isseq; 483 484 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 485 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 486 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 487 } 488 if (v != originalv) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 489 PetscFunctionReturn(0); 490 } 491 492 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 493 { 494 DM dm; 495 PetscBool ishdf5; 496 PetscErrorCode ierr; 497 498 PetscFunctionBegin; 499 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 500 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 501 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 502 if (ishdf5) { 503 DM dmBC; 504 Vec gv; 505 const char *name; 506 507 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 508 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 509 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 510 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 511 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 512 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 513 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 514 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 515 } else { 516 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 517 } 518 PetscFunctionReturn(0); 519 } 520 521 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 522 { 523 DM dm; 524 PetscBool ishdf5,isexodusii; 525 PetscErrorCode ierr; 526 527 PetscFunctionBegin; 528 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 529 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 530 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 531 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr); 532 if (ishdf5) { 533 #if defined(PETSC_HAVE_HDF5) 534 ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 535 #else 536 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 537 #endif 538 } else if (isexodusii) { 539 #if defined(PETSC_HAVE_EXODUSII) 540 ierr = VecLoad_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr); 541 #else 542 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 543 #endif 544 } else { 545 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 546 } 547 PetscFunctionReturn(0); 548 } 549 550 PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 551 { 552 DM dm; 553 PetscViewerFormat format; 554 PetscBool ishdf5; 555 PetscErrorCode ierr; 556 557 PetscFunctionBegin; 558 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 559 if (!dm) SETERRQ(PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 560 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 561 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 562 if (format == PETSC_VIEWER_NATIVE) { 563 if (dm->useNatural) { 564 if (dm->sfNatural) { 565 if (ishdf5) { 566 #if defined(PETSC_HAVE_HDF5) 567 Vec v; 568 const char *vecname; 569 570 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 571 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 572 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 573 ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 574 ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 575 ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 576 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 577 #else 578 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 579 #endif 580 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 581 } 582 } else { 583 ierr = VecLoad_Default(originalv, viewer);CHKERRQ(ierr); 584 } 585 } 586 PetscFunctionReturn(0); 587 } 588 589 PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 590 { 591 PetscSection coordSection; 592 Vec coordinates; 593 DMLabel depthLabel, celltypeLabel; 594 const char *name[4]; 595 const PetscScalar *a; 596 PetscInt dim, pStart, pEnd, cStart, cEnd, c; 597 PetscErrorCode ierr; 598 599 PetscFunctionBegin; 600 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 601 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 602 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 603 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 604 ierr = DMPlexGetCellTypeLabel(dm, &celltypeLabel);CHKERRQ(ierr); 605 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 606 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 607 ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 608 name[0] = "vertex"; 609 name[1] = "edge"; 610 name[dim-1] = "face"; 611 name[dim] = "cell"; 612 for (c = cStart; c < cEnd; ++c) { 613 PetscInt *closure = NULL; 614 PetscInt closureSize, cl, ct; 615 616 ierr = DMLabelGetValue(celltypeLabel, c, &ct);CHKERRQ(ierr); 617 ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]);CHKERRQ(ierr); 618 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 619 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 620 for (cl = 0; cl < closureSize*2; cl += 2) { 621 PetscInt point = closure[cl], depth, dof, off, d, p; 622 623 if ((point < pStart) || (point >= pEnd)) continue; 624 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 625 if (!dof) continue; 626 ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 627 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 628 ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr); 629 for (p = 0; p < dof/dim; ++p) { 630 ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 631 for (d = 0; d < dim; ++d) { 632 if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 633 ierr = PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 634 } 635 ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 636 } 637 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 638 } 639 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 640 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 641 } 642 ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 643 PetscFunctionReturn(0); 644 } 645 646 static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 647 { 648 DM_Plex *mesh = (DM_Plex*) dm->data; 649 DM cdm; 650 PetscSection coordSection; 651 Vec coordinates; 652 PetscViewerFormat format; 653 PetscErrorCode ierr; 654 655 PetscFunctionBegin; 656 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 657 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 658 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 659 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 660 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 661 const char *name; 662 PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 663 PetscInt pStart, pEnd, p, numLabels, l; 664 PetscMPIInt rank, size; 665 666 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 667 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 668 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 669 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 670 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 671 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 672 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 673 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 674 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 675 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 676 ierr = PetscViewerASCIIPrintf(viewer, "Supports:\n", name);CHKERRQ(ierr); 677 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 678 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize);CHKERRQ(ierr); 679 for (p = pStart; p < pEnd; ++p) { 680 PetscInt dof, off, s; 681 682 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 683 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 684 for (s = off; s < off+dof; ++s) { 685 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 686 } 687 } 688 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 689 ierr = PetscViewerASCIIPrintf(viewer, "Cones:\n", name);CHKERRQ(ierr); 690 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize);CHKERRQ(ierr); 691 for (p = pStart; p < pEnd; ++p) { 692 PetscInt dof, off, c; 693 694 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 695 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 696 for (c = off; c < off+dof; ++c) { 697 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 698 } 699 } 700 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 701 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 702 if (coordSection && coordinates) { 703 ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr); 704 } 705 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 706 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 707 for (l = 0; l < numLabels; ++l) { 708 DMLabel label; 709 PetscBool isdepth; 710 const char *name; 711 712 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 713 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 714 if (isdepth) continue; 715 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 716 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 717 } 718 if (size > 1) { 719 PetscSF sf; 720 721 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 722 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 723 } 724 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 725 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 726 const char *name, *color; 727 const char *defcolors[3] = {"gray", "orange", "green"}; 728 const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 729 char lname[PETSC_MAX_PATH_LEN]; 730 PetscReal scale = 2.0; 731 PetscReal tikzscale = 1.0; 732 PetscBool useNumbers = PETSC_TRUE, useLabels, useColors; 733 double tcoords[3]; 734 PetscScalar *coords; 735 PetscInt numLabels, l, numColors, numLColors, dim, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 736 PetscMPIInt rank, size; 737 char **names, **colors, **lcolors; 738 PetscBool plotEdges, flg, lflg; 739 PetscBT wp = NULL; 740 PetscInt pEnd, pStart; 741 742 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 743 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 744 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 745 numLabels = PetscMax(numLabels, 10); 746 numColors = 10; 747 numLColors = 10; 748 ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 749 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 750 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL);CHKERRQ(ierr); 751 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 752 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 753 if (!useLabels) numLabels = 0; 754 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 755 if (!useColors) { 756 numColors = 3; 757 for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 758 } 759 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 760 if (!useColors) { 761 numLColors = 4; 762 for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 763 } 764 ierr = PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg);CHKERRQ(ierr); 765 plotEdges = (PetscBool)(depth > 1 && useNumbers && dim < 3); 766 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg);CHKERRQ(ierr); 767 if (flg && plotEdges && depth < dim) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 768 if (depth < dim) plotEdges = PETSC_FALSE; 769 770 /* filter points with labelvalue != labeldefaultvalue */ 771 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 772 if (lflg) { 773 DMLabel lbl; 774 775 ierr = DMGetLabel(dm, lname, &lbl);CHKERRQ(ierr); 776 if (lbl) { 777 PetscInt val, defval; 778 779 ierr = DMLabelGetDefaultValue(lbl, &defval);CHKERRQ(ierr); 780 ierr = PetscBTCreate(pEnd-pStart, &wp);CHKERRQ(ierr); 781 for (c = pStart; c < pEnd; c++) { 782 PetscInt *closure = NULL; 783 PetscInt closureSize; 784 785 ierr = DMLabelGetValue(lbl, c, &val);CHKERRQ(ierr); 786 if (val == defval) continue; 787 788 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 789 for (p = 0; p < closureSize*2; p += 2) { 790 ierr = PetscBTSet(wp, closure[p] - pStart);CHKERRQ(ierr); 791 } 792 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 793 } 794 } 795 } 796 797 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 798 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr); 799 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 800 ierr = PetscViewerASCIIPrintf(viewer, "\ 801 \\documentclass[tikz]{standalone}\n\n\ 802 \\usepackage{pgflibraryshapes}\n\ 803 \\usetikzlibrary{backgrounds}\n\ 804 \\usetikzlibrary{arrows}\n\ 805 \\begin{document}\n");CHKERRQ(ierr); 806 if (size > 1) { 807 ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 808 for (p = 0; p < size; ++p) { 809 if (p > 0 && p == size-1) { 810 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 811 } else if (p > 0) { 812 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 813 } 814 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 815 } 816 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 817 } 818 ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale);CHKERRQ(ierr); 819 820 /* Plot vertices */ 821 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 822 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 823 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 824 for (v = vStart; v < vEnd; ++v) { 825 PetscInt off, dof, d; 826 PetscBool isLabeled = PETSC_FALSE; 827 828 if (wp && !PetscBTLookup(wp,v - pStart)) continue; 829 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 830 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 831 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 832 if (PetscUnlikely(dof > 3)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 833 for (d = 0; d < dof; ++d) { 834 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 835 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 836 } 837 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 838 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 839 for (d = 0; d < dof; ++d) { 840 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 841 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]);CHKERRQ(ierr); 842 } 843 color = colors[rank%numColors]; 844 for (l = 0; l < numLabels; ++l) { 845 PetscInt val; 846 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 847 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 848 } 849 if (useNumbers) { 850 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 851 } else { 852 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 853 } 854 } 855 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 856 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 857 /* Plot cells */ 858 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 859 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 860 if (dim == 3 || !useNumbers) { 861 for (e = eStart; e < eEnd; ++e) { 862 const PetscInt *cone; 863 864 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 865 color = colors[rank%numColors]; 866 for (l = 0; l < numLabels; ++l) { 867 PetscInt val; 868 ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 869 if (val >= 0) {color = lcolors[l%numLColors]; break;} 870 } 871 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 872 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 873 } 874 } else { 875 for (c = cStart; c < cEnd; ++c) { 876 PetscInt *closure = NULL; 877 PetscInt closureSize, firstPoint = -1; 878 879 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 880 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 881 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 882 for (p = 0; p < closureSize*2; p += 2) { 883 const PetscInt point = closure[p]; 884 885 if ((point < vStart) || (point >= vEnd)) continue; 886 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 887 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", point, rank);CHKERRQ(ierr); 888 if (firstPoint < 0) firstPoint = point; 889 } 890 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 891 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d);\n", firstPoint, rank);CHKERRQ(ierr); 892 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 893 } 894 } 895 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 896 for (c = cStart; c < cEnd; ++c) { 897 double ccoords[3] = {0.0, 0.0, 0.0}; 898 PetscBool isLabeled = PETSC_FALSE; 899 PetscInt *closure = NULL; 900 PetscInt closureSize, dof, d, n = 0; 901 902 if (wp && !PetscBTLookup(wp,c - pStart)) continue; 903 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 904 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 905 for (p = 0; p < closureSize*2; p += 2) { 906 const PetscInt point = closure[p]; 907 PetscInt off; 908 909 if ((point < vStart) || (point >= vEnd)) continue; 910 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 911 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 912 for (d = 0; d < dof; ++d) { 913 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 914 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 915 } 916 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 917 if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 918 for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 919 ++n; 920 } 921 for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 922 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 923 for (d = 0; d < dof; ++d) { 924 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 925 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]);CHKERRQ(ierr); 926 } 927 color = colors[rank%numColors]; 928 for (l = 0; l < numLabels; ++l) { 929 PetscInt val; 930 ierr = DMGetLabelValue(dm, names[l], c, &val);CHKERRQ(ierr); 931 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 932 } 933 if (useNumbers) { 934 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c);CHKERRQ(ierr); 935 } else { 936 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 937 } 938 } 939 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 940 /* Plot edges */ 941 if (plotEdges) { 942 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 943 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 944 for (e = eStart; e < eEnd; ++e) { 945 const PetscInt *cone; 946 PetscInt coneSize, offA, offB, dof, d; 947 948 if (wp && !PetscBTLookup(wp,e - pStart)) continue; 949 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 950 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 951 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 952 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 953 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 954 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 955 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 956 for (d = 0; d < dof; ++d) { 957 tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 958 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 959 } 960 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 961 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 962 for (d = 0; d < dof; ++d) { 963 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 964 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr); 965 } 966 color = colors[rank%numColors]; 967 for (l = 0; l < numLabels; ++l) { 968 PetscInt val; 969 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 970 if (val >= 0) {color = lcolors[l%numLColors]; break;} 971 } 972 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 973 } 974 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 975 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 976 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 977 } 978 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 979 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 980 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 981 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 982 for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 983 for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 984 for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 985 ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 986 ierr = PetscBTDestroy(&wp);CHKERRQ(ierr); 987 } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 988 Vec cown,acown; 989 VecScatter sct; 990 ISLocalToGlobalMapping g2l; 991 IS gid,acis; 992 MPI_Comm comm,ncomm = MPI_COMM_NULL; 993 MPI_Group ggroup,ngroup; 994 PetscScalar *array,nid; 995 const PetscInt *idxs; 996 PetscInt *idxs2,*start,*adjacency,*work; 997 PetscInt64 lm[3],gm[3]; 998 PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 999 PetscMPIInt d1,d2,rank; 1000 1001 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1002 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 1003 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1004 ierr = MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm);CHKERRMPI(ierr); 1005 #endif 1006 if (ncomm != MPI_COMM_NULL) { 1007 ierr = MPI_Comm_group(comm,&ggroup);CHKERRMPI(ierr); 1008 ierr = MPI_Comm_group(ncomm,&ngroup);CHKERRMPI(ierr); 1009 d1 = 0; 1010 ierr = MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2);CHKERRMPI(ierr); 1011 nid = d2; 1012 ierr = MPI_Group_free(&ggroup);CHKERRMPI(ierr); 1013 ierr = MPI_Group_free(&ngroup);CHKERRMPI(ierr); 1014 ierr = MPI_Comm_free(&ncomm);CHKERRMPI(ierr); 1015 } else nid = 0.0; 1016 1017 /* Get connectivity */ 1018 ierr = DMPlexGetVTKCellHeight(dm,&cellHeight);CHKERRQ(ierr); 1019 ierr = DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid);CHKERRQ(ierr); 1020 1021 /* filter overlapped local cells */ 1022 ierr = DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd);CHKERRQ(ierr); 1023 ierr = ISGetIndices(gid,&idxs);CHKERRQ(ierr); 1024 ierr = ISGetLocalSize(gid,&cum);CHKERRQ(ierr); 1025 ierr = PetscMalloc1(cum,&idxs2);CHKERRQ(ierr); 1026 for (c = cStart, cum = 0; c < cEnd; c++) { 1027 if (idxs[c-cStart] < 0) continue; 1028 idxs2[cum++] = idxs[c-cStart]; 1029 } 1030 ierr = ISRestoreIndices(gid,&idxs);CHKERRQ(ierr); 1031 if (numVertices != cum) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum); 1032 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1033 ierr = ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid);CHKERRQ(ierr); 1034 1035 /* support for node-aware cell locality */ 1036 ierr = ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis);CHKERRQ(ierr); 1037 ierr = VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown);CHKERRQ(ierr); 1038 ierr = VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown);CHKERRQ(ierr); 1039 ierr = VecGetArray(cown,&array);CHKERRQ(ierr); 1040 for (c = 0; c < numVertices; c++) array[c] = nid; 1041 ierr = VecRestoreArray(cown,&array);CHKERRQ(ierr); 1042 ierr = VecScatterCreate(cown,acis,acown,NULL,&sct);CHKERRQ(ierr); 1043 ierr = VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1044 ierr = VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1045 ierr = ISDestroy(&acis);CHKERRQ(ierr); 1046 ierr = VecScatterDestroy(&sct);CHKERRQ(ierr); 1047 ierr = VecDestroy(&cown);CHKERRQ(ierr); 1048 1049 /* compute edgeCut */ 1050 for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 1051 ierr = PetscMalloc1(cum,&work);CHKERRQ(ierr); 1052 ierr = ISLocalToGlobalMappingCreateIS(gid,&g2l);CHKERRQ(ierr); 1053 ierr = ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 1054 ierr = ISDestroy(&gid);CHKERRQ(ierr); 1055 ierr = VecGetArray(acown,&array);CHKERRQ(ierr); 1056 for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 1057 PetscInt totl; 1058 1059 totl = start[c+1]-start[c]; 1060 ierr = ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work);CHKERRQ(ierr); 1061 for (i = 0; i < totl; i++) { 1062 if (work[i] < 0) { 1063 ect += 1; 1064 ectn += (array[i + start[c]] != nid) ? 0 : 1; 1065 } 1066 } 1067 } 1068 ierr = PetscFree(work);CHKERRQ(ierr); 1069 ierr = VecRestoreArray(acown,&array);CHKERRQ(ierr); 1070 lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 1071 lm[1] = -numVertices; 1072 ierr = MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm);CHKERRMPI(ierr); 1073 ierr = PetscViewerASCIIPrintf(viewer," Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]);CHKERRQ(ierr); 1074 lm[0] = ect; /* edgeCut */ 1075 lm[1] = ectn; /* node-aware edgeCut */ 1076 lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 1077 ierr = MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr); 1078 ierr = PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]);CHKERRQ(ierr); 1079 #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1080 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),gm[0] ? ((double)(gm[1]))/((double)gm[0]) : 1.);CHKERRQ(ierr); 1081 #else 1082 ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0);CHKERRQ(ierr); 1083 #endif 1084 ierr = ISLocalToGlobalMappingDestroy(&g2l);CHKERRQ(ierr); 1085 ierr = PetscFree(start);CHKERRQ(ierr); 1086 ierr = PetscFree(adjacency);CHKERRQ(ierr); 1087 ierr = VecDestroy(&acown);CHKERRQ(ierr); 1088 } else { 1089 const char *name; 1090 PetscInt *sizes, *hybsizes, *ghostsizes; 1091 PetscInt locDepth, depth, cellHeight, dim, d; 1092 PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1093 PetscInt numLabels, l; 1094 DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1095 MPI_Comm comm; 1096 PetscMPIInt size, rank; 1097 1098 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1099 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1100 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1101 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1102 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 1103 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 1104 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1105 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1106 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 1107 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 1108 ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRMPI(ierr); 1109 ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr); 1110 gcNum = gcEnd - gcStart; 1111 ierr = PetscCalloc3(size,&sizes,size,&hybsizes,size,&ghostsizes);CHKERRQ(ierr); 1112 for (d = 0; d <= depth; d++) { 1113 PetscInt Nc[2] = {0, 0}, ict; 1114 1115 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 1116 if (pStart < pEnd) {ierr = DMPlexGetCellType(dm, pStart, &ct0);CHKERRQ(ierr);} 1117 ict = ct0; 1118 ierr = MPI_Bcast(&ict, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1119 ct0 = (DMPolytopeType) ict; 1120 for (p = pStart; p < pEnd; ++p) { 1121 DMPolytopeType ct; 1122 1123 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 1124 if (ct == ct0) ++Nc[0]; 1125 else ++Nc[1]; 1126 } 1127 ierr = MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1128 ierr = MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1129 if (d == depth) {ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);} 1130 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", (depth == 1) && d ? dim : d);CHKERRQ(ierr); 1131 for (p = 0; p < size; ++p) { 1132 if (!rank) { 1133 ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]);CHKERRQ(ierr); 1134 if (hybsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]);CHKERRQ(ierr);} 1135 if (ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);} 1136 } 1137 } 1138 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 1139 } 1140 ierr = PetscFree3(sizes,hybsizes,ghostsizes);CHKERRQ(ierr); 1141 { 1142 const PetscReal *maxCell; 1143 const PetscReal *L; 1144 const DMBoundaryType *bd; 1145 PetscBool per, localized; 1146 1147 ierr = DMGetPeriodicity(dm, &per, &maxCell, &L, &bd);CHKERRQ(ierr); 1148 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 1149 if (per) { 1150 ierr = PetscViewerASCIIPrintf(viewer, "Periodic mesh (");CHKERRQ(ierr); 1151 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1152 for (d = 0; d < dim; ++d) { 1153 if (bd && d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1154 if (bd) {ierr = PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]]);CHKERRQ(ierr);} 1155 } 1156 ierr = PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized");CHKERRQ(ierr); 1157 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1158 } 1159 } 1160 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 1161 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 1162 for (l = 0; l < numLabels; ++l) { 1163 DMLabel label; 1164 const char *name; 1165 IS valueIS; 1166 const PetscInt *values; 1167 PetscInt numValues, v; 1168 1169 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 1170 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1171 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 1172 ierr = PetscViewerASCIIPrintf(viewer, " %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr); 1173 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 1174 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 1175 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1176 for (v = 0; v < numValues; ++v) { 1177 PetscInt size; 1178 1179 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 1180 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1181 ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr); 1182 } 1183 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 1184 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1185 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 1186 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 1187 } 1188 { 1189 char **labelNames; 1190 PetscInt Nl = numLabels; 1191 PetscBool flg; 1192 1193 ierr = PetscMalloc1(Nl, &labelNames);CHKERRQ(ierr); 1194 ierr = PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg);CHKERRQ(ierr); 1195 for (l = 0; l < Nl; ++l) { 1196 DMLabel label; 1197 1198 ierr = DMHasLabel(dm, labelNames[l], &flg);CHKERRQ(ierr); 1199 if (flg) { 1200 ierr = DMGetLabel(dm, labelNames[l], &label);CHKERRQ(ierr); 1201 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 1202 } 1203 ierr = PetscFree(labelNames[l]);CHKERRQ(ierr); 1204 } 1205 ierr = PetscFree(labelNames);CHKERRQ(ierr); 1206 } 1207 /* If no fields are specified, people do not want to see adjacency */ 1208 if (dm->Nf) { 1209 PetscInt f; 1210 1211 for (f = 0; f < dm->Nf; ++f) { 1212 const char *name; 1213 1214 ierr = PetscObjectGetName(dm->fields[f].disc, &name);CHKERRQ(ierr); 1215 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Field %s:\n", name);CHKERRQ(ierr);} 1216 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1217 if (dm->fields[f].label) {ierr = DMLabelView(dm->fields[f].label, viewer);CHKERRQ(ierr);} 1218 if (dm->fields[f].adjacency[0]) { 1219 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n");CHKERRQ(ierr);} 1220 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM\n");CHKERRQ(ierr);} 1221 } else { 1222 if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FEM\n");CHKERRQ(ierr);} 1223 else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n");CHKERRQ(ierr);} 1224 } 1225 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1226 } 1227 } 1228 ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr); 1229 if (cdm) { 1230 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1231 ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr); 1232 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1233 } 1234 } 1235 PetscFunctionReturn(0); 1236 } 1237 1238 static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1239 { 1240 DMPolytopeType ct; 1241 PetscMPIInt rank; 1242 PetscErrorCode ierr; 1243 1244 PetscFunctionBegin; 1245 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1246 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1247 switch (ct) { 1248 case DM_POLYTOPE_TRIANGLE: 1249 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1250 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1251 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1252 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1253 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1254 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1255 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1256 break; 1257 case DM_POLYTOPE_QUADRILATERAL: 1258 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1259 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1260 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1261 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1262 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1263 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1264 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1265 PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1266 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1267 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1268 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1269 ierr = PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1270 break; 1271 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1272 } 1273 PetscFunctionReturn(0); 1274 } 1275 1276 static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1277 { 1278 DMPolytopeType ct; 1279 PetscReal centroid[2] = {0., 0.}; 1280 PetscMPIInt rank; 1281 PetscInt fillColor, v, e, d; 1282 PetscErrorCode ierr; 1283 1284 PetscFunctionBegin; 1285 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1286 ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1287 fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2; 1288 switch (ct) { 1289 case DM_POLYTOPE_TRIANGLE: 1290 { 1291 PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1292 1293 for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;} 1294 for (e = 0; e < 3; ++e) { 1295 refCoords[0] = refVertices[e*2+0]; 1296 refCoords[1] = refVertices[e*2+1]; 1297 for (d = 1; d <= edgeDiv; ++d) { 1298 refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv; 1299 refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv; 1300 } 1301 ierr = DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords);CHKERRQ(ierr); 1302 for (d = 0; d < edgeDiv; ++d) { 1303 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); 1304 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); 1305 } 1306 } 1307 } 1308 break; 1309 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1310 } 1311 PetscFunctionReturn(0); 1312 } 1313 1314 static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1315 { 1316 PetscDraw draw; 1317 DM cdm; 1318 PetscSection coordSection; 1319 Vec coordinates; 1320 const PetscScalar *coords; 1321 PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1322 PetscReal *refCoords, *edgeCoords; 1323 PetscBool isnull, drawAffine = PETSC_TRUE; 1324 PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1325 PetscErrorCode ierr; 1326 1327 PetscFunctionBegin; 1328 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 1329 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim); 1330 ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL);CHKERRQ(ierr); 1331 if (!drawAffine) {ierr = PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords);CHKERRQ(ierr);} 1332 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 1333 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1334 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 1335 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1336 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1337 1338 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 1339 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 1340 if (isnull) PetscFunctionReturn(0); 1341 ierr = PetscDrawSetTitle(draw, "Mesh");CHKERRQ(ierr); 1342 1343 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 1344 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 1345 for (c = 0; c < N; c += dim) { 1346 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 1347 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1348 } 1349 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 1350 ierr = MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1351 ierr = MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1352 ierr = PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]);CHKERRQ(ierr); 1353 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 1354 1355 for (c = cStart; c < cEnd; ++c) { 1356 PetscScalar *coords = NULL; 1357 PetscInt numCoords; 1358 1359 ierr = DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords);CHKERRQ(ierr); 1360 if (drawAffine) { 1361 ierr = DMPlexDrawCell(dm, draw, c, coords);CHKERRQ(ierr); 1362 } else { 1363 ierr = DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords);CHKERRQ(ierr); 1364 } 1365 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 1366 } 1367 if (!drawAffine) {ierr = PetscFree2(refCoords, edgeCoords);CHKERRQ(ierr);} 1368 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1369 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 1370 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 1371 PetscFunctionReturn(0); 1372 } 1373 1374 #if defined(PETSC_HAVE_EXODUSII) 1375 #include <exodusII.h> 1376 #include <petscviewerexodusii.h> 1377 #endif 1378 1379 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1380 { 1381 PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1382 char name[PETSC_MAX_PATH_LEN]; 1383 PetscErrorCode ierr; 1384 1385 PetscFunctionBegin; 1386 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1387 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1388 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1389 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1390 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1391 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 1392 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 1393 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus);CHKERRQ(ierr); 1394 if (iascii) { 1395 PetscViewerFormat format; 1396 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1397 if (format == PETSC_VIEWER_ASCII_GLVIS) { 1398 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1399 } else { 1400 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 1401 } 1402 } else if (ishdf5) { 1403 #if defined(PETSC_HAVE_HDF5) 1404 ierr = DMPlexView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1405 #else 1406 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1407 #endif 1408 } else if (isvtk) { 1409 ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr); 1410 } else if (isdraw) { 1411 ierr = DMPlexView_Draw(dm, viewer);CHKERRQ(ierr); 1412 } else if (isglvis) { 1413 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1414 #if defined(PETSC_HAVE_EXODUSII) 1415 } else if (isexodus) { 1416 /* 1417 exodusII requires that all sets be part of exactly one cell set. 1418 If the dm does not have a "Cell Sets" label defined, we create one 1419 with ID 1, containig all cells. 1420 Note that if the Cell Sets label is defined but does not cover all cells, 1421 we may still have a problem. This should probably be checked here or in the viewer; 1422 */ 1423 PetscInt numCS; 1424 ierr = DMGetLabelSize(dm,"Cell Sets",&numCS);CHKERRQ(ierr); 1425 if (!numCS) { 1426 PetscInt cStart, cEnd, c; 1427 ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr); 1428 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1429 for (c = cStart; c < cEnd; ++c) {ierr = DMSetLabelValue(dm, "Cell Sets", c, 1);CHKERRQ(ierr);} 1430 } 1431 ierr = DMView_PlexExodusII(dm, viewer);CHKERRQ(ierr); 1432 #endif 1433 } else { 1434 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1435 } 1436 /* Optionally view the partition */ 1437 ierr = PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg);CHKERRQ(ierr); 1438 if (flg) { 1439 Vec ranks; 1440 ierr = DMPlexCreateRankField(dm, &ranks);CHKERRQ(ierr); 1441 ierr = VecView(ranks, viewer);CHKERRQ(ierr); 1442 ierr = VecDestroy(&ranks);CHKERRQ(ierr); 1443 } 1444 /* Optionally view a label */ 1445 ierr = PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg);CHKERRQ(ierr); 1446 if (flg) { 1447 DMLabel label; 1448 Vec val; 1449 1450 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1451 if (!label) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 1452 ierr = DMPlexCreateLabelField(dm, label, &val);CHKERRQ(ierr); 1453 ierr = VecView(val, viewer);CHKERRQ(ierr); 1454 ierr = VecDestroy(&val);CHKERRQ(ierr); 1455 } 1456 PetscFunctionReturn(0); 1457 } 1458 1459 /*@ 1460 DMPlexTopologyView - Saves a DMPlex topology into a file 1461 1462 Collective on DM 1463 1464 Input Parameters: 1465 + dm - The DM whose topology is to be saved 1466 - viewer - The PetscViewer for saving 1467 1468 Level: advanced 1469 1470 .seealso: DMView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexTopologyLoad() 1471 @*/ 1472 PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 1473 { 1474 PetscBool ishdf5; 1475 PetscErrorCode ierr; 1476 1477 PetscFunctionBegin; 1478 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1479 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1480 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1481 if (ishdf5) { 1482 #if defined(PETSC_HAVE_HDF5) 1483 PetscViewerFormat format; 1484 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1485 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1486 IS globalPointNumbering; 1487 1488 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1489 ierr = DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1490 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1491 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 1492 #else 1493 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1494 #endif 1495 } 1496 PetscFunctionReturn(0); 1497 } 1498 1499 /*@ 1500 DMPlexCoordinatesView - Saves DMPlex coordinates into a file 1501 1502 Collective on DM 1503 1504 Input Parameters: 1505 + dm - The DM whose coordinates are to be saved 1506 - viewer - The PetscViewer for saving 1507 1508 Level: advanced 1509 1510 .seealso: DMView(), DMPlexTopologyView(), DMPlexLabelsView(), DMPlexCoordinatesLoad() 1511 @*/ 1512 PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 1513 { 1514 PetscBool ishdf5; 1515 PetscErrorCode ierr; 1516 1517 PetscFunctionBegin; 1518 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1519 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1520 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1521 if (ishdf5) { 1522 #if defined(PETSC_HAVE_HDF5) 1523 PetscViewerFormat format; 1524 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1525 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1526 ierr = DMPlexCoordinatesView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1527 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1528 #else 1529 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1530 #endif 1531 } 1532 PetscFunctionReturn(0); 1533 } 1534 1535 /*@ 1536 DMPlexLabelsView - Saves DMPlex labels into a file 1537 1538 Collective on DM 1539 1540 Input Parameters: 1541 + dm - The DM whose labels are to be saved 1542 - viewer - The PetscViewer for saving 1543 1544 Level: advanced 1545 1546 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsLoad() 1547 @*/ 1548 PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 1549 { 1550 PetscBool ishdf5; 1551 PetscErrorCode ierr; 1552 1553 PetscFunctionBegin; 1554 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1555 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1556 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1557 if (ishdf5) { 1558 #if defined(PETSC_HAVE_HDF5) 1559 IS globalPointNumbering; 1560 PetscViewerFormat format; 1561 1562 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1563 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1564 ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr); 1565 ierr = DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr); 1566 ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr); 1567 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1568 #else 1569 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1570 #endif 1571 } 1572 PetscFunctionReturn(0); 1573 } 1574 1575 /*@ 1576 DMPlexSectionView - Saves a section associated with a DMPlex 1577 1578 Collective on DM 1579 1580 Input Parameters: 1581 + dm - The DM that contains the topology on which the section to be saved is defined 1582 . viewer - The PetscViewer for saving 1583 - sectiondm - The DM that contains the section to be saved 1584 1585 Level: advanced 1586 1587 Notes: 1588 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. 1589 1590 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. 1591 1592 .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexGlobalVectorView(), DMPlexLocalVectorView(), PetscSectionView(), DMPlexSectionLoad() 1593 @*/ 1594 PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 1595 { 1596 PetscBool ishdf5; 1597 PetscErrorCode ierr; 1598 1599 PetscFunctionBegin; 1600 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1601 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1602 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1603 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 1604 if (ishdf5) { 1605 #if defined(PETSC_HAVE_HDF5) 1606 ierr = DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm);CHKERRQ(ierr); 1607 #else 1608 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1609 #endif 1610 } 1611 PetscFunctionReturn(0); 1612 } 1613 1614 /*@ 1615 DMPlexGlobalVectorView - Saves a global vector 1616 1617 Collective on DM 1618 1619 Input Parameters: 1620 + dm - The DM that represents the topology 1621 . viewer - The PetscViewer to save data with 1622 . sectiondm - The DM that contains the global section on which vec is defined 1623 - vec - The global vector to be saved 1624 1625 Level: advanced 1626 1627 Notes: 1628 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. 1629 1630 Typical calling sequence 1631 $ DMCreate(PETSC_COMM_WORLD, &dm); 1632 $ DMSetType(dm, DMPLEX); 1633 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1634 $ DMClone(dm, §iondm); 1635 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1636 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1637 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1638 $ PetscSectionSetChart(section, pStart, pEnd); 1639 $ PetscSectionSetUp(section); 1640 $ DMSetLocalSection(sectiondm, section); 1641 $ PetscSectionDestroy(§ion); 1642 $ DMGetGlobalVector(sectiondm, &vec); 1643 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1644 $ DMPlexTopologyView(dm, viewer); 1645 $ DMPlexSectionView(dm, viewer, sectiondm); 1646 $ DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 1647 $ DMRestoreGlobalVector(sectiondm, &vec); 1648 $ DMDestroy(§iondm); 1649 $ DMDestroy(&dm); 1650 1651 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexLocalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1652 @*/ 1653 PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1654 { 1655 PetscBool ishdf5; 1656 PetscErrorCode ierr; 1657 1658 PetscFunctionBegin; 1659 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1660 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1661 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1662 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1663 /* Check consistency */ 1664 { 1665 PetscSection section; 1666 PetscBool includesConstraints; 1667 PetscInt m, m1; 1668 1669 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1670 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 1671 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1672 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1673 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1674 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 1675 } 1676 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1677 if (ishdf5) { 1678 #if defined(PETSC_HAVE_HDF5) 1679 ierr = DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1680 #else 1681 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1682 #endif 1683 } 1684 PetscFunctionReturn(0); 1685 } 1686 1687 /*@ 1688 DMPlexLocalVectorView - Saves a local vector 1689 1690 Collective on DM 1691 1692 Input Parameters: 1693 + dm - The DM that represents the topology 1694 . viewer - The PetscViewer to save data with 1695 . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm 1696 - vec - The local vector to be saved 1697 1698 Level: advanced 1699 1700 Notes: 1701 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. 1702 1703 Typical calling sequence 1704 $ DMCreate(PETSC_COMM_WORLD, &dm); 1705 $ DMSetType(dm, DMPLEX); 1706 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1707 $ DMClone(dm, §iondm); 1708 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1709 $ PetscSectionCreate(PETSC_COMM_WORLD, §ion); 1710 $ DMPlexGetChart(sectiondm, &pStart, &pEnd); 1711 $ PetscSectionSetChart(section, pStart, pEnd); 1712 $ PetscSectionSetUp(section); 1713 $ DMSetLocalSection(sectiondm, section); 1714 $ DMGetLocalVector(sectiondm, &vec); 1715 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1716 $ DMPlexTopologyView(dm, viewer); 1717 $ DMPlexSectionView(dm, viewer, sectiondm); 1718 $ DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 1719 $ DMRestoreLocalVector(sectiondm, &vec); 1720 $ DMDestroy(§iondm); 1721 $ DMDestroy(&dm); 1722 1723 .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexGlobalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad() 1724 @*/ 1725 PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 1726 { 1727 PetscBool ishdf5; 1728 PetscErrorCode ierr; 1729 1730 PetscFunctionBegin; 1731 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1732 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1733 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1734 PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 1735 /* Check consistency */ 1736 { 1737 PetscSection section; 1738 PetscBool includesConstraints; 1739 PetscInt m, m1; 1740 1741 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 1742 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 1743 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 1744 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 1745 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 1746 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 1747 } 1748 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1749 if (ishdf5) { 1750 #if defined(PETSC_HAVE_HDF5) 1751 ierr = DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr); 1752 #else 1753 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1754 #endif 1755 } 1756 PetscFunctionReturn(0); 1757 } 1758 1759 PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 1760 { 1761 PetscBool ishdf5; 1762 PetscErrorCode ierr; 1763 1764 PetscFunctionBegin; 1765 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1766 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1767 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1768 if (ishdf5) { 1769 #if defined(PETSC_HAVE_HDF5) 1770 PetscViewerFormat format; 1771 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1772 if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 1773 ierr = DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer);CHKERRQ(ierr); 1774 } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1775 ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1776 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1777 PetscFunctionReturn(0); 1778 #else 1779 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1780 #endif 1781 } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 1782 } 1783 1784 /*@ 1785 DMPlexTopologyLoad - Loads a topology into a DMPlex 1786 1787 Collective on DM 1788 1789 Input Parameters: 1790 + dm - The DM into which the topology is loaded 1791 - viewer - The PetscViewer for the saved topology 1792 1793 Output Parameters: 1794 . 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 1795 1796 Level: advanced 1797 1798 .seealso: DMLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1799 @*/ 1800 PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 1801 { 1802 PetscBool ishdf5; 1803 PetscErrorCode ierr; 1804 1805 PetscFunctionBegin; 1806 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1807 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1808 if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3); 1809 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1810 if (ishdf5) { 1811 #if defined(PETSC_HAVE_HDF5) 1812 PetscViewerFormat format; 1813 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1814 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1815 ierr = DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr); 1816 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1817 #else 1818 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1819 #endif 1820 } 1821 PetscFunctionReturn(0); 1822 } 1823 1824 /*@ 1825 DMPlexCoordinatesLoad - Loads coordinates into a DMPlex 1826 1827 Collective on DM 1828 1829 Input Parameters: 1830 + dm - The DM into which the coordinates are loaded 1831 - viewer - The PetscViewer for the saved coordinates 1832 1833 Level: advanced 1834 1835 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1836 @*/ 1837 PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer) 1838 { 1839 PetscBool ishdf5; 1840 PetscErrorCode ierr; 1841 1842 PetscFunctionBegin; 1843 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1844 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1845 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1846 if (ishdf5) { 1847 #if defined(PETSC_HAVE_HDF5) 1848 PetscViewerFormat format; 1849 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1850 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1851 ierr = DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1852 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1853 #else 1854 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1855 #endif 1856 } 1857 PetscFunctionReturn(0); 1858 } 1859 1860 /*@ 1861 DMPlexLabelsLoad - Loads labels into a DMPlex 1862 1863 Collective on DM 1864 1865 Input Parameters: 1866 + dm - The DM into which the labels are loaded 1867 - viewer - The PetscViewer for the saved labels 1868 1869 Level: advanced 1870 1871 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat() 1872 @*/ 1873 PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer) 1874 { 1875 PetscBool ishdf5; 1876 PetscErrorCode ierr; 1877 1878 PetscFunctionBegin; 1879 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1880 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1881 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1882 if (ishdf5) { 1883 #if defined(PETSC_HAVE_HDF5) 1884 PetscViewerFormat format; 1885 1886 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1887 if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 1888 ierr = DMPlexLabelsLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1889 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 1890 #else 1891 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1892 #endif 1893 } 1894 PetscFunctionReturn(0); 1895 } 1896 1897 /*@ 1898 DMPlexSectionLoad - Loads section into a DMPlex 1899 1900 Collective on DM 1901 1902 Input Parameters: 1903 + dm - The DM that represents the topology 1904 . viewer - The PetscViewer that represents the on-disk section (sectionA) 1905 . sectiondm - The DM into which the on-disk section (sectionA) is migrated 1906 - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer 1907 1908 Output Parameters 1909 + 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) 1910 - 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) 1911 1912 Level: advanced 1913 1914 Notes: 1915 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. 1916 1917 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. 1918 1919 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. 1920 1921 Example using 2 processes: 1922 $ NX (number of points on dm): 4 1923 $ sectionA : the on-disk section 1924 $ vecA : a vector associated with sectionA 1925 $ sectionB : sectiondm's local section constructed in this function 1926 $ vecB (local) : a vector associated with sectiondm's local section 1927 $ vecB (global) : a vector associated with sectiondm's global section 1928 $ 1929 $ rank 0 rank 1 1930 $ vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 1931 $ sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 1932 $ sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 1933 $ sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 1934 $ [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 1935 $ sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 1936 $ sectionB->atlasDof : 1 0 1 | 1 3 1937 $ sectionB->atlasOff (no perm) : 0 1 1 | 0 1 1938 $ vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 1939 $ vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 1940 $ 1941 $ where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 1942 1943 .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad(), PetscSectionLoad(), DMPlexSectionView() 1944 @*/ 1945 PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 1946 { 1947 PetscBool ishdf5; 1948 PetscErrorCode ierr; 1949 1950 PetscFunctionBegin; 1951 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1952 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1953 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 1954 PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 1955 if (globalDofSF) PetscValidPointer(globalDofSF, 5); 1956 if (localDofSF) PetscValidPointer(localDofSF, 6); 1957 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 1958 if (ishdf5) { 1959 #if defined(PETSC_HAVE_HDF5) 1960 ierr = DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF);CHKERRQ(ierr); 1961 #else 1962 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1963 #endif 1964 } 1965 PetscFunctionReturn(0); 1966 } 1967 1968 /*@ 1969 DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 1970 1971 Collective on DM 1972 1973 Input Parameters: 1974 + dm - The DM that represents the topology 1975 . viewer - The PetscViewer that represents the on-disk vector data 1976 . sectiondm - The DM that contains the global section on which vec is defined 1977 . sf - The SF that migrates the on-disk vector data into vec 1978 - vec - The global vector to set values of 1979 1980 Level: advanced 1981 1982 Notes: 1983 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. 1984 1985 Typical calling sequence 1986 $ DMCreate(PETSC_COMM_WORLD, &dm); 1987 $ DMSetType(dm, DMPLEX); 1988 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 1989 $ DMPlexTopologyLoad(dm, viewer, &sfX); 1990 $ DMClone(dm, §iondm); 1991 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 1992 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 1993 $ DMGetGlobalVector(sectiondm, &vec); 1994 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 1995 $ DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 1996 $ DMRestoreGlobalVector(sectiondm, &vec); 1997 $ PetscSFDestroy(&gsf); 1998 $ PetscSFDestroy(&sfX); 1999 $ DMDestroy(§iondm); 2000 $ DMDestroy(&dm); 2001 2002 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexLocalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2003 @*/ 2004 PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2005 { 2006 PetscBool ishdf5; 2007 PetscErrorCode ierr; 2008 2009 PetscFunctionBegin; 2010 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2011 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2012 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2013 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2014 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2015 /* Check consistency */ 2016 { 2017 PetscSection section; 2018 PetscBool includesConstraints; 2019 PetscInt m, m1; 2020 2021 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2022 ierr = DMGetGlobalSection(sectiondm, §ion);CHKERRQ(ierr); 2023 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2024 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2025 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2026 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m); 2027 } 2028 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2029 if (ishdf5) { 2030 #if defined(PETSC_HAVE_HDF5) 2031 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2032 #else 2033 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2034 #endif 2035 } 2036 PetscFunctionReturn(0); 2037 } 2038 2039 /*@ 2040 DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 2041 2042 Collective on DM 2043 2044 Input Parameters: 2045 + dm - The DM that represents the topology 2046 . viewer - The PetscViewer that represents the on-disk vector data 2047 . sectiondm - The DM that contains the local section on which vec is defined 2048 . sf - The SF that migrates the on-disk vector data into vec 2049 - vec - The local vector to set values of 2050 2051 Level: advanced 2052 2053 Notes: 2054 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. 2055 2056 Typical calling sequence 2057 $ DMCreate(PETSC_COMM_WORLD, &dm); 2058 $ DMSetType(dm, DMPLEX); 2059 $ PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2060 $ DMPlexTopologyLoad(dm, viewer, &sfX); 2061 $ DMClone(dm, §iondm); 2062 $ PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2063 $ DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2064 $ DMGetLocalVector(sectiondm, &vec); 2065 $ PetscObjectSetName((PetscObject)vec, "vec_name"); 2066 $ DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2067 $ DMRestoreLocalVector(sectiondm, &vec); 2068 $ PetscSFDestroy(&lsf); 2069 $ PetscSFDestroy(&sfX); 2070 $ DMDestroy(§iondm); 2071 $ DMDestroy(&dm); 2072 2073 .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexGlobalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView() 2074 @*/ 2075 PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2076 { 2077 PetscBool ishdf5; 2078 PetscErrorCode ierr; 2079 2080 PetscFunctionBegin; 2081 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2082 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2083 PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2084 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 2085 PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 2086 /* Check consistency */ 2087 { 2088 PetscSection section; 2089 PetscBool includesConstraints; 2090 PetscInt m, m1; 2091 2092 ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr); 2093 ierr = DMGetLocalSection(sectiondm, §ion);CHKERRQ(ierr); 2094 ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr); 2095 if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);} 2096 else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);} 2097 if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m); 2098 } 2099 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2100 if (ishdf5) { 2101 #if defined(PETSC_HAVE_HDF5) 2102 ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr); 2103 #else 2104 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2105 #endif 2106 } 2107 PetscFunctionReturn(0); 2108 } 2109 2110 PetscErrorCode DMDestroy_Plex(DM dm) 2111 { 2112 DM_Plex *mesh = (DM_Plex*) dm->data; 2113 PetscErrorCode ierr; 2114 2115 PetscFunctionBegin; 2116 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr); 2117 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr); 2118 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL);CHKERRQ(ierr); 2119 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL);CHKERRQ(ierr); 2120 if (--mesh->refct > 0) PetscFunctionReturn(0); 2121 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 2122 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 2123 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 2124 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 2125 ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr); 2126 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 2127 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 2128 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 2129 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 2130 ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 2131 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 2132 ierr = ISDestroy(&mesh->subpointIS);CHKERRQ(ierr); 2133 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 2134 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 2135 ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 2136 ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 2137 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 2138 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 2139 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 2140 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 2141 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 2142 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 2143 ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr); 2144 ierr = PetscFree(mesh->neighbors);CHKERRQ(ierr); 2145 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 2146 ierr = PetscFree(mesh);CHKERRQ(ierr); 2147 PetscFunctionReturn(0); 2148 } 2149 2150 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2151 { 2152 PetscSection sectionGlobal; 2153 PetscInt bs = -1, mbs; 2154 PetscInt localSize; 2155 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2156 PetscErrorCode ierr; 2157 MatType mtype; 2158 ISLocalToGlobalMapping ltog; 2159 2160 PetscFunctionBegin; 2161 ierr = MatInitializePackage();CHKERRQ(ierr); 2162 mtype = dm->mattype; 2163 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 2164 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 2165 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 2166 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 2167 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 2168 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 2169 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 2170 ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr); 2171 if (mbs > 1) bs = mbs; 2172 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 2173 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 2174 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 2175 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 2176 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 2177 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 2178 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 2179 ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr); 2180 if (!isShell) { 2181 PetscSection subSection; 2182 PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 2183 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *ltogidx, lsize; 2184 PetscInt pStart, pEnd, p, dof, cdof; 2185 2186 /* Set localtoglobalmapping on the matrix for MatSetValuesLocal() to work (it also creates the local matrices in case of MATIS) */ 2187 if (isMatIS) { /* need a different l2g map than the one computed by DMGetLocalToGlobalMapping */ 2188 PetscSection section; 2189 PetscInt size; 2190 2191 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 2192 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 2193 ierr = PetscMalloc1(size,<ogidx);CHKERRQ(ierr); 2194 ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr); 2195 } else { 2196 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 2197 } 2198 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 2199 for (p = pStart, lsize = 0; p < pEnd; ++p) { 2200 PetscInt bdof; 2201 2202 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 2203 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 2204 dof = dof < 0 ? -(dof+1) : dof; 2205 bdof = cdof && (dof-cdof) ? 1 : dof; 2206 if (dof) { 2207 if (bs < 0) {bs = bdof;} 2208 else if (bs != bdof) {bs = 1; if (!isMatIS) break;} 2209 } 2210 if (isMatIS) { 2211 PetscInt loff,c,off; 2212 ierr = PetscSectionGetOffset(subSection, p, &loff);CHKERRQ(ierr); 2213 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 2214 for (c = 0; c < dof-cdof; ++c, ++lsize) ltogidx[loff+c] = off > -1 ? off+c : -(off+1)+c; 2215 } 2216 } 2217 /* Must have same blocksize on all procs (some might have no points) */ 2218 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 2219 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 2220 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 2221 else {bs = bsMinMax[0];} 2222 bs = PetscMax(1,bs); 2223 if (isMatIS) { /* Must reduce indices by blocksize */ 2224 PetscInt l; 2225 2226 lsize = lsize/bs; 2227 if (bs > 1) for (l = 0; l < lsize; ++l) ltogidx[l] = ltogidx[l*bs]/bs; 2228 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, lsize, ltogidx, PETSC_OWN_POINTER, <og);CHKERRQ(ierr); 2229 } 2230 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 2231 if (isMatIS) { 2232 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 2233 } 2234 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 2235 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 2236 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 2237 } 2238 ierr = MatSetDM(*J, dm);CHKERRQ(ierr); 2239 PetscFunctionReturn(0); 2240 } 2241 2242 /*@ 2243 DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2244 2245 Not collective 2246 2247 Input Parameter: 2248 . mesh - The DMPlex 2249 2250 Output Parameters: 2251 . subsection - The subdomain section 2252 2253 Level: developer 2254 2255 .seealso: 2256 @*/ 2257 PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2258 { 2259 DM_Plex *mesh = (DM_Plex*) dm->data; 2260 PetscErrorCode ierr; 2261 2262 PetscFunctionBegin; 2263 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2264 if (!mesh->subdomainSection) { 2265 PetscSection section; 2266 PetscSF sf; 2267 2268 ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr); 2269 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 2270 ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr); 2271 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 2272 } 2273 *subsection = mesh->subdomainSection; 2274 PetscFunctionReturn(0); 2275 } 2276 2277 /*@ 2278 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 2279 2280 Not collective 2281 2282 Input Parameter: 2283 . mesh - The DMPlex 2284 2285 Output Parameters: 2286 + pStart - The first mesh point 2287 - pEnd - The upper bound for mesh points 2288 2289 Level: beginner 2290 2291 .seealso: DMPlexCreate(), DMPlexSetChart() 2292 @*/ 2293 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2294 { 2295 DM_Plex *mesh = (DM_Plex*) dm->data; 2296 PetscErrorCode ierr; 2297 2298 PetscFunctionBegin; 2299 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2300 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2301 PetscFunctionReturn(0); 2302 } 2303 2304 /*@ 2305 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 2306 2307 Not collective 2308 2309 Input Parameters: 2310 + mesh - The DMPlex 2311 . pStart - The first mesh point 2312 - pEnd - The upper bound for mesh points 2313 2314 Output Parameters: 2315 2316 Level: beginner 2317 2318 .seealso: DMPlexCreate(), DMPlexGetChart() 2319 @*/ 2320 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2321 { 2322 DM_Plex *mesh = (DM_Plex*) dm->data; 2323 PetscErrorCode ierr; 2324 2325 PetscFunctionBegin; 2326 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2327 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 2328 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 2329 PetscFunctionReturn(0); 2330 } 2331 2332 /*@ 2333 DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2334 2335 Not collective 2336 2337 Input Parameters: 2338 + mesh - The DMPlex 2339 - p - The point, which must lie in the chart set with DMPlexSetChart() 2340 2341 Output Parameter: 2342 . size - The cone size for point p 2343 2344 Level: beginner 2345 2346 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2347 @*/ 2348 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2349 { 2350 DM_Plex *mesh = (DM_Plex*) dm->data; 2351 PetscErrorCode ierr; 2352 2353 PetscFunctionBegin; 2354 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2355 PetscValidPointer(size, 3); 2356 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2357 PetscFunctionReturn(0); 2358 } 2359 2360 /*@ 2361 DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2362 2363 Not collective 2364 2365 Input Parameters: 2366 + mesh - The DMPlex 2367 . p - The point, which must lie in the chart set with DMPlexSetChart() 2368 - size - The cone size for point p 2369 2370 Output Parameter: 2371 2372 Note: 2373 This should be called after DMPlexSetChart(). 2374 2375 Level: beginner 2376 2377 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 2378 @*/ 2379 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2380 { 2381 DM_Plex *mesh = (DM_Plex*) dm->data; 2382 PetscErrorCode ierr; 2383 2384 PetscFunctionBegin; 2385 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2386 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2387 2388 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 2389 PetscFunctionReturn(0); 2390 } 2391 2392 /*@ 2393 DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 2394 2395 Not collective 2396 2397 Input Parameters: 2398 + mesh - The DMPlex 2399 . p - The point, which must lie in the chart set with DMPlexSetChart() 2400 - size - The additional cone size for point p 2401 2402 Output Parameter: 2403 2404 Note: 2405 This should be called after DMPlexSetChart(). 2406 2407 Level: beginner 2408 2409 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 2410 @*/ 2411 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 2412 { 2413 DM_Plex *mesh = (DM_Plex*) dm->data; 2414 PetscInt csize; 2415 PetscErrorCode ierr; 2416 2417 PetscFunctionBegin; 2418 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2419 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 2420 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 2421 2422 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 2423 PetscFunctionReturn(0); 2424 } 2425 2426 /*@C 2427 DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2428 2429 Not collective 2430 2431 Input Parameters: 2432 + dm - The DMPlex 2433 - p - The point, which must lie in the chart set with DMPlexSetChart() 2434 2435 Output Parameter: 2436 . cone - An array of points which are on the in-edges for point p 2437 2438 Level: beginner 2439 2440 Fortran Notes: 2441 Since it returns an array, this routine is only available in Fortran 90, and you must 2442 include petsc.h90 in your code. 2443 You must also call DMPlexRestoreCone() after you finish using the returned array. 2444 DMPlexRestoreCone() is not needed/available in C. 2445 2446 .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart() 2447 @*/ 2448 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 2449 { 2450 DM_Plex *mesh = (DM_Plex*) dm->data; 2451 PetscInt off; 2452 PetscErrorCode ierr; 2453 2454 PetscFunctionBegin; 2455 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2456 PetscValidPointer(cone, 3); 2457 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2458 *cone = &mesh->cones[off]; 2459 PetscFunctionReturn(0); 2460 } 2461 2462 /*@C 2463 DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 2464 2465 Not collective 2466 2467 Input Parameters: 2468 + dm - The DMPlex 2469 - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 2470 2471 Output Parameter: 2472 + pConesSection - PetscSection describing the layout of pCones 2473 - pCones - An array of points which are on the in-edges for the point set p 2474 2475 Level: intermediate 2476 2477 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart() 2478 @*/ 2479 PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 2480 { 2481 PetscSection cs, newcs; 2482 PetscInt *cones; 2483 PetscInt *newarr=NULL; 2484 PetscInt n; 2485 PetscErrorCode ierr; 2486 2487 PetscFunctionBegin; 2488 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 2489 ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr); 2490 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 2491 if (pConesSection) *pConesSection = newcs; 2492 if (pCones) { 2493 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 2494 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr); 2495 } 2496 PetscFunctionReturn(0); 2497 } 2498 2499 /*@ 2500 DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 2501 2502 Not collective 2503 2504 Input Parameters: 2505 + dm - The DMPlex 2506 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2507 2508 Output Parameter: 2509 . expandedPoints - An array of vertices recursively expanded from input points 2510 2511 Level: advanced 2512 2513 Notes: 2514 Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 2515 There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 2516 2517 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth() 2518 @*/ 2519 PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 2520 { 2521 IS *expandedPointsAll; 2522 PetscInt depth; 2523 PetscErrorCode ierr; 2524 2525 PetscFunctionBegin; 2526 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2527 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2528 PetscValidPointer(expandedPoints, 3); 2529 ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2530 *expandedPoints = expandedPointsAll[0]; 2531 ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]);CHKERRQ(ierr); 2532 ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 2533 PetscFunctionReturn(0); 2534 } 2535 2536 /*@ 2537 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). 2538 2539 Not collective 2540 2541 Input Parameters: 2542 + dm - The DMPlex 2543 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2544 2545 Output Parameter: 2546 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2547 . expandedPoints - (optional) An array of index sets with recursively expanded cones 2548 - sections - (optional) An array of sections which describe mappings from points to their cone points 2549 2550 Level: advanced 2551 2552 Notes: 2553 Like DMPlexGetConeTuple() but recursive. 2554 2555 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. 2556 For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 2557 2558 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: 2559 (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 2560 (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 2561 2562 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2563 @*/ 2564 PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2565 { 2566 const PetscInt *arr0=NULL, *cone=NULL; 2567 PetscInt *arr=NULL, *newarr=NULL; 2568 PetscInt d, depth_, i, n, newn, cn, co, start, end; 2569 IS *expandedPoints_; 2570 PetscSection *sections_; 2571 PetscErrorCode ierr; 2572 2573 PetscFunctionBegin; 2574 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2575 PetscValidHeaderSpecific(points, IS_CLASSID, 2); 2576 if (depth) PetscValidIntPointer(depth, 3); 2577 if (expandedPoints) PetscValidPointer(expandedPoints, 4); 2578 if (sections) PetscValidPointer(sections, 5); 2579 ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr); 2580 ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr); 2581 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2582 ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr); 2583 ierr = PetscCalloc1(depth_, §ions_);CHKERRQ(ierr); 2584 arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 2585 for (d=depth_-1; d>=0; d--) { 2586 ierr = PetscSectionCreate(PETSC_COMM_SELF, §ions_[d]);CHKERRQ(ierr); 2587 ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr); 2588 for (i=0; i<n; i++) { 2589 ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr); 2590 if (arr[i] >= start && arr[i] < end) { 2591 ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr); 2592 ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr); 2593 } else { 2594 ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr); 2595 } 2596 } 2597 ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr); 2598 ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr); 2599 ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr); 2600 for (i=0; i<n; i++) { 2601 ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr); 2602 ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr); 2603 if (cn > 1) { 2604 ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr); 2605 ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr); 2606 } else { 2607 newarr[co] = arr[i]; 2608 } 2609 } 2610 ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr); 2611 arr = newarr; 2612 n = newn; 2613 } 2614 ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr); 2615 *depth = depth_; 2616 if (expandedPoints) *expandedPoints = expandedPoints_; 2617 else { 2618 for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);} 2619 ierr = PetscFree(expandedPoints_);CHKERRQ(ierr); 2620 } 2621 if (sections) *sections = sections_; 2622 else { 2623 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(§ions_[d]);CHKERRQ(ierr);} 2624 ierr = PetscFree(sections_);CHKERRQ(ierr); 2625 } 2626 PetscFunctionReturn(0); 2627 } 2628 2629 /*@ 2630 DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 2631 2632 Not collective 2633 2634 Input Parameters: 2635 + dm - The DMPlex 2636 - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 2637 2638 Output Parameter: 2639 + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 2640 . expandedPoints - (optional) An array of recursively expanded cones 2641 - sections - (optional) An array of sections which describe mappings from points to their cone points 2642 2643 Level: advanced 2644 2645 Notes: 2646 See DMPlexGetConeRecursive() for details. 2647 2648 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 2649 @*/ 2650 PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 2651 { 2652 PetscInt d, depth_; 2653 PetscErrorCode ierr; 2654 2655 PetscFunctionBegin; 2656 ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 2657 if (depth && *depth != depth_) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 2658 if (depth) *depth = 0; 2659 if (expandedPoints) { 2660 for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);} 2661 ierr = PetscFree(*expandedPoints);CHKERRQ(ierr); 2662 } 2663 if (sections) { 2664 for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);} 2665 ierr = PetscFree(*sections);CHKERRQ(ierr); 2666 } 2667 PetscFunctionReturn(0); 2668 } 2669 2670 /*@ 2671 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 2672 2673 Not collective 2674 2675 Input Parameters: 2676 + mesh - The DMPlex 2677 . p - The point, which must lie in the chart set with DMPlexSetChart() 2678 - cone - An array of points which are on the in-edges for point p 2679 2680 Output Parameter: 2681 2682 Note: 2683 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2684 2685 Developer Note: Why not call this DMPlexSetCover() 2686 2687 Level: beginner 2688 2689 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize() 2690 @*/ 2691 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 2692 { 2693 DM_Plex *mesh = (DM_Plex*) dm->data; 2694 PetscInt pStart, pEnd; 2695 PetscInt dof, off, c; 2696 PetscErrorCode ierr; 2697 2698 PetscFunctionBegin; 2699 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2700 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2701 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2702 if (dof) PetscValidPointer(cone, 3); 2703 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2704 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); 2705 for (c = 0; c < dof; ++c) { 2706 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); 2707 mesh->cones[off+c] = cone[c]; 2708 } 2709 PetscFunctionReturn(0); 2710 } 2711 2712 /*@C 2713 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 2714 2715 Not collective 2716 2717 Input Parameters: 2718 + mesh - The DMPlex 2719 - p - The point, which must lie in the chart set with DMPlexSetChart() 2720 2721 Output Parameter: 2722 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2723 integer giving the prescription for cone traversal. If it is negative, the cone is 2724 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 2725 the index of the cone point on which to start. 2726 2727 Level: beginner 2728 2729 Fortran Notes: 2730 Since it returns an array, this routine is only available in Fortran 90, and you must 2731 include petsc.h90 in your code. 2732 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 2733 DMPlexRestoreConeOrientation() is not needed/available in C. 2734 2735 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 2736 @*/ 2737 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 2738 { 2739 DM_Plex *mesh = (DM_Plex*) dm->data; 2740 PetscInt off; 2741 PetscErrorCode ierr; 2742 2743 PetscFunctionBegin; 2744 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2745 if (PetscDefined(USE_DEBUG)) { 2746 PetscInt dof; 2747 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2748 if (dof) PetscValidPointer(coneOrientation, 3); 2749 } 2750 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2751 2752 *coneOrientation = &mesh->coneOrientations[off]; 2753 PetscFunctionReturn(0); 2754 } 2755 2756 /*@ 2757 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 2758 2759 Not collective 2760 2761 Input Parameters: 2762 + mesh - The DMPlex 2763 . p - The point, which must lie in the chart set with DMPlexSetChart() 2764 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2765 integer giving the prescription for cone traversal. If it is negative, the cone is 2766 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 2767 the index of the cone point on which to start. 2768 2769 Output Parameter: 2770 2771 Note: 2772 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2773 2774 Level: beginner 2775 2776 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2777 @*/ 2778 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 2779 { 2780 DM_Plex *mesh = (DM_Plex*) dm->data; 2781 PetscInt pStart, pEnd; 2782 PetscInt dof, off, c; 2783 PetscErrorCode ierr; 2784 2785 PetscFunctionBegin; 2786 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2787 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2788 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2789 if (dof) PetscValidPointer(coneOrientation, 3); 2790 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2791 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); 2792 for (c = 0; c < dof; ++c) { 2793 PetscInt cdof, o = coneOrientation[c]; 2794 2795 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 2796 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); 2797 mesh->coneOrientations[off+c] = o; 2798 } 2799 PetscFunctionReturn(0); 2800 } 2801 2802 /*@ 2803 DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 2804 2805 Not collective 2806 2807 Input Parameters: 2808 + mesh - The DMPlex 2809 . p - The point, which must lie in the chart set with DMPlexSetChart() 2810 . conePos - The local index in the cone where the point should be put 2811 - conePoint - The mesh point to insert 2812 2813 Level: beginner 2814 2815 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2816 @*/ 2817 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 2818 { 2819 DM_Plex *mesh = (DM_Plex*) dm->data; 2820 PetscInt pStart, pEnd; 2821 PetscInt dof, off; 2822 PetscErrorCode ierr; 2823 2824 PetscFunctionBegin; 2825 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2826 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2827 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); 2828 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); 2829 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2830 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2831 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); 2832 mesh->cones[off+conePos] = conePoint; 2833 PetscFunctionReturn(0); 2834 } 2835 2836 /*@ 2837 DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 2838 2839 Not collective 2840 2841 Input Parameters: 2842 + mesh - The DMPlex 2843 . p - The point, which must lie in the chart set with DMPlexSetChart() 2844 . conePos - The local index in the cone where the point should be put 2845 - coneOrientation - The point orientation to insert 2846 2847 Level: beginner 2848 2849 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2850 @*/ 2851 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 2852 { 2853 DM_Plex *mesh = (DM_Plex*) dm->data; 2854 PetscInt pStart, pEnd; 2855 PetscInt dof, off; 2856 PetscErrorCode ierr; 2857 2858 PetscFunctionBegin; 2859 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2860 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2861 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); 2862 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2863 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2864 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); 2865 mesh->coneOrientations[off+conePos] = coneOrientation; 2866 PetscFunctionReturn(0); 2867 } 2868 2869 /*@ 2870 DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 2871 2872 Not collective 2873 2874 Input Parameters: 2875 + mesh - The DMPlex 2876 - p - The point, which must lie in the chart set with DMPlexSetChart() 2877 2878 Output Parameter: 2879 . size - The support size for point p 2880 2881 Level: beginner 2882 2883 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 2884 @*/ 2885 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 2886 { 2887 DM_Plex *mesh = (DM_Plex*) dm->data; 2888 PetscErrorCode ierr; 2889 2890 PetscFunctionBegin; 2891 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2892 PetscValidPointer(size, 3); 2893 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 2894 PetscFunctionReturn(0); 2895 } 2896 2897 /*@ 2898 DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 2899 2900 Not collective 2901 2902 Input Parameters: 2903 + mesh - The DMPlex 2904 . p - The point, which must lie in the chart set with DMPlexSetChart() 2905 - size - The support size for point p 2906 2907 Output Parameter: 2908 2909 Note: 2910 This should be called after DMPlexSetChart(). 2911 2912 Level: beginner 2913 2914 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 2915 @*/ 2916 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 2917 { 2918 DM_Plex *mesh = (DM_Plex*) dm->data; 2919 PetscErrorCode ierr; 2920 2921 PetscFunctionBegin; 2922 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2923 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 2924 2925 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 2926 PetscFunctionReturn(0); 2927 } 2928 2929 /*@C 2930 DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 2931 2932 Not collective 2933 2934 Input Parameters: 2935 + mesh - The DMPlex 2936 - p - The point, which must lie in the chart set with DMPlexSetChart() 2937 2938 Output Parameter: 2939 . support - An array of points which are on the out-edges for point p 2940 2941 Level: beginner 2942 2943 Fortran Notes: 2944 Since it returns an array, this routine is only available in Fortran 90, and you must 2945 include petsc.h90 in your code. 2946 You must also call DMPlexRestoreSupport() after you finish using the returned array. 2947 DMPlexRestoreSupport() is not needed/available in C. 2948 2949 .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart() 2950 @*/ 2951 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 2952 { 2953 DM_Plex *mesh = (DM_Plex*) dm->data; 2954 PetscInt off; 2955 PetscErrorCode ierr; 2956 2957 PetscFunctionBegin; 2958 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2959 PetscValidPointer(support, 3); 2960 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 2961 *support = &mesh->supports[off]; 2962 PetscFunctionReturn(0); 2963 } 2964 2965 /*@ 2966 DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 2967 2968 Not collective 2969 2970 Input Parameters: 2971 + mesh - The DMPlex 2972 . p - The point, which must lie in the chart set with DMPlexSetChart() 2973 - support - An array of points which are on the out-edges for point p 2974 2975 Output Parameter: 2976 2977 Note: 2978 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 2979 2980 Level: beginner 2981 2982 .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 2983 @*/ 2984 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 2985 { 2986 DM_Plex *mesh = (DM_Plex*) dm->data; 2987 PetscInt pStart, pEnd; 2988 PetscInt dof, off, c; 2989 PetscErrorCode ierr; 2990 2991 PetscFunctionBegin; 2992 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2993 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 2994 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 2995 if (dof) PetscValidPointer(support, 3); 2996 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 2997 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 2998 for (c = 0; c < dof; ++c) { 2999 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); 3000 mesh->supports[off+c] = support[c]; 3001 } 3002 PetscFunctionReturn(0); 3003 } 3004 3005 /*@ 3006 DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 3007 3008 Not collective 3009 3010 Input Parameters: 3011 + mesh - The DMPlex 3012 . p - The point, which must lie in the chart set with DMPlexSetChart() 3013 . supportPos - The local index in the cone where the point should be put 3014 - supportPoint - The mesh point to insert 3015 3016 Level: beginner 3017 3018 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 3019 @*/ 3020 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3021 { 3022 DM_Plex *mesh = (DM_Plex*) dm->data; 3023 PetscInt pStart, pEnd; 3024 PetscInt dof, off; 3025 PetscErrorCode ierr; 3026 3027 PetscFunctionBegin; 3028 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3029 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 3030 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3031 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 3032 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); 3033 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); 3034 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); 3035 mesh->supports[off+supportPos] = supportPoint; 3036 PetscFunctionReturn(0); 3037 } 3038 3039 /*@C 3040 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 3041 3042 Not collective 3043 3044 Input Parameters: 3045 + mesh - The DMPlex 3046 . p - The point, which must lie in the chart set with DMPlexSetChart() 3047 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 3048 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 3049 3050 Output Parameters: 3051 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3052 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3053 3054 Note: 3055 If using internal storage (points is NULL on input), each call overwrites the last output. 3056 3057 Fortran Notes: 3058 Since it returns an array, this routine is only available in Fortran 90, and you must 3059 include petsc.h90 in your code. 3060 3061 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3062 3063 Level: beginner 3064 3065 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3066 @*/ 3067 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3068 { 3069 DM_Plex *mesh = (DM_Plex*) dm->data; 3070 PetscInt *closure, *fifo; 3071 const PetscInt *tmp = NULL, *tmpO = NULL; 3072 PetscInt tmpSize, t; 3073 PetscInt depth = 0, maxSize; 3074 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 3075 PetscErrorCode ierr; 3076 3077 PetscFunctionBegin; 3078 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3079 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3080 /* This is only 1-level */ 3081 if (useCone) { 3082 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 3083 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 3084 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 3085 } else { 3086 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 3087 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 3088 } 3089 if (depth == 1) { 3090 if (*points) { 3091 closure = *points; 3092 } else { 3093 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 3094 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 3095 } 3096 closure[0] = p; closure[1] = 0; 3097 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 3098 closure[closureSize] = tmp[t]; 3099 closure[closureSize+1] = tmpO ? tmpO[t] : 0; 3100 } 3101 if (numPoints) *numPoints = closureSize/2; 3102 if (points) *points = closure; 3103 PetscFunctionReturn(0); 3104 } 3105 { 3106 PetscInt c, coneSeries, s,supportSeries; 3107 3108 c = mesh->maxConeSize; 3109 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 3110 s = mesh->maxSupportSize; 3111 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 3112 maxSize = 2*PetscMax(coneSeries,supportSeries); 3113 } 3114 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3115 if (*points) { 3116 closure = *points; 3117 } else { 3118 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 3119 } 3120 closure[0] = p; closure[1] = 0; 3121 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 3122 const PetscInt cp = tmp[t]; 3123 const PetscInt co = tmpO ? tmpO[t] : 0; 3124 3125 closure[closureSize] = cp; 3126 closure[closureSize+1] = co; 3127 fifo[fifoSize] = cp; 3128 fifo[fifoSize+1] = co; 3129 } 3130 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3131 while (fifoSize - fifoStart) { 3132 const PetscInt q = fifo[fifoStart]; 3133 const PetscInt o = fifo[fifoStart+1]; 3134 const PetscInt rev = o >= 0 ? 0 : 1; 3135 const PetscInt off = rev ? -(o+1) : o; 3136 3137 if (useCone) { 3138 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 3139 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 3140 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 3141 } else { 3142 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 3143 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 3144 tmpO = NULL; 3145 } 3146 for (t = 0; t < tmpSize; ++t) { 3147 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 3148 const PetscInt cp = tmp[i]; 3149 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 3150 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 3151 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 3152 PetscInt co = tmpO ? tmpO[i] : 0; 3153 PetscInt c; 3154 3155 if (rev) { 3156 PetscInt childSize, coff; 3157 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 3158 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 3159 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 3160 } 3161 /* Check for duplicate */ 3162 for (c = 0; c < closureSize; c += 2) { 3163 if (closure[c] == cp) break; 3164 } 3165 if (c == closureSize) { 3166 closure[closureSize] = cp; 3167 closure[closureSize+1] = co; 3168 fifo[fifoSize] = cp; 3169 fifo[fifoSize+1] = co; 3170 closureSize += 2; 3171 fifoSize += 2; 3172 } 3173 } 3174 fifoStart += 2; 3175 } 3176 if (numPoints) *numPoints = closureSize/2; 3177 if (points) *points = closure; 3178 ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3179 PetscFunctionReturn(0); 3180 } 3181 3182 /*@C 3183 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 3184 3185 Not collective 3186 3187 Input Parameters: 3188 + mesh - The DMPlex 3189 . p - The point, which must lie in the chart set with DMPlexSetChart() 3190 . orientation - The orientation of the point 3191 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 3192 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 3193 3194 Output Parameters: 3195 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 3196 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 3197 3198 Note: 3199 If using internal storage (points is NULL on input), each call overwrites the last output. 3200 3201 Fortran Notes: 3202 Since it returns an array, this routine is only available in Fortran 90, and you must 3203 include petsc.h90 in your code. 3204 3205 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3206 3207 Level: beginner 3208 3209 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3210 @*/ 3211 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3212 { 3213 DM_Plex *mesh = (DM_Plex*) dm->data; 3214 PetscInt *closure, *fifo; 3215 const PetscInt *tmp = NULL, *tmpO = NULL; 3216 PetscInt tmpSize, t; 3217 PetscInt depth = 0, maxSize; 3218 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 3219 PetscErrorCode ierr; 3220 3221 PetscFunctionBegin; 3222 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3223 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3224 /* This is only 1-level */ 3225 if (useCone) { 3226 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 3227 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 3228 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 3229 } else { 3230 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 3231 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 3232 } 3233 if (depth == 1) { 3234 if (*points) { 3235 closure = *points; 3236 } else { 3237 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 3238 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 3239 } 3240 closure[0] = p; closure[1] = ornt; 3241 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 3242 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 3243 closure[closureSize] = tmp[i]; 3244 closure[closureSize+1] = tmpO ? tmpO[i] : 0; 3245 } 3246 if (numPoints) *numPoints = closureSize/2; 3247 if (points) *points = closure; 3248 PetscFunctionReturn(0); 3249 } 3250 { 3251 PetscInt c, coneSeries, s,supportSeries; 3252 3253 c = mesh->maxConeSize; 3254 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 3255 s = mesh->maxSupportSize; 3256 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 3257 maxSize = 2*PetscMax(coneSeries,supportSeries); 3258 } 3259 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3260 if (*points) { 3261 closure = *points; 3262 } else { 3263 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 3264 } 3265 closure[0] = p; closure[1] = ornt; 3266 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 3267 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 3268 const PetscInt cp = tmp[i]; 3269 PetscInt co = tmpO ? tmpO[i] : 0; 3270 3271 if (ornt < 0) { 3272 PetscInt childSize, coff; 3273 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 3274 coff = co < 0 ? -(tmpO[i]+1) : tmpO[i]; 3275 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 3276 } 3277 closure[closureSize] = cp; 3278 closure[closureSize+1] = co; 3279 fifo[fifoSize] = cp; 3280 fifo[fifoSize+1] = co; 3281 } 3282 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3283 while (fifoSize - fifoStart) { 3284 const PetscInt q = fifo[fifoStart]; 3285 const PetscInt o = fifo[fifoStart+1]; 3286 const PetscInt rev = o >= 0 ? 0 : 1; 3287 const PetscInt off = rev ? -(o+1) : o; 3288 3289 if (useCone) { 3290 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 3291 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 3292 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 3293 } else { 3294 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 3295 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 3296 tmpO = NULL; 3297 } 3298 for (t = 0; t < tmpSize; ++t) { 3299 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 3300 const PetscInt cp = tmp[i]; 3301 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 3302 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 3303 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 3304 PetscInt co = tmpO ? tmpO[i] : 0; 3305 PetscInt c; 3306 3307 if (rev) { 3308 PetscInt childSize, coff; 3309 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 3310 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 3311 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 3312 } 3313 /* Check for duplicate */ 3314 for (c = 0; c < closureSize; c += 2) { 3315 if (closure[c] == cp) break; 3316 } 3317 if (c == closureSize) { 3318 closure[closureSize] = cp; 3319 closure[closureSize+1] = co; 3320 fifo[fifoSize] = cp; 3321 fifo[fifoSize+1] = co; 3322 closureSize += 2; 3323 fifoSize += 2; 3324 } 3325 } 3326 fifoStart += 2; 3327 } 3328 if (numPoints) *numPoints = closureSize/2; 3329 if (points) *points = closure; 3330 ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 3331 PetscFunctionReturn(0); 3332 } 3333 3334 /*@C 3335 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 3336 3337 Not collective 3338 3339 Input Parameters: 3340 + mesh - The DMPlex 3341 . p - The point, which must lie in the chart set with DMPlexSetChart() 3342 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 3343 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints, zeroed on exit 3344 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...], zeroed on exit 3345 3346 Note: 3347 If not using internal storage (points is not NULL on input), this call is unnecessary 3348 3349 Fortran Notes: 3350 Since it returns an array, this routine is only available in Fortran 90, and you must 3351 include petsc.h90 in your code. 3352 3353 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3354 3355 Level: beginner 3356 3357 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 3358 @*/ 3359 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3360 { 3361 PetscErrorCode ierr; 3362 3363 PetscFunctionBegin; 3364 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3365 if (numPoints) PetscValidIntPointer(numPoints,4); 3366 if (points) PetscValidPointer(points,5); 3367 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr); 3368 if (numPoints) *numPoints = 0; 3369 PetscFunctionReturn(0); 3370 } 3371 3372 /*@ 3373 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 3374 3375 Not collective 3376 3377 Input Parameter: 3378 . mesh - The DMPlex 3379 3380 Output Parameters: 3381 + maxConeSize - The maximum number of in-edges 3382 - maxSupportSize - The maximum number of out-edges 3383 3384 Level: beginner 3385 3386 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 3387 @*/ 3388 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 3389 { 3390 DM_Plex *mesh = (DM_Plex*) dm->data; 3391 3392 PetscFunctionBegin; 3393 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3394 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 3395 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 3396 PetscFunctionReturn(0); 3397 } 3398 3399 PetscErrorCode DMSetUp_Plex(DM dm) 3400 { 3401 DM_Plex *mesh = (DM_Plex*) dm->data; 3402 PetscInt size; 3403 PetscErrorCode ierr; 3404 3405 PetscFunctionBegin; 3406 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3407 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 3408 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 3409 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 3410 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 3411 ierr = PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt));CHKERRQ(ierr); 3412 if (mesh->maxSupportSize) { 3413 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3414 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 3415 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 3416 ierr = PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt));CHKERRQ(ierr); 3417 } 3418 PetscFunctionReturn(0); 3419 } 3420 3421 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 3422 { 3423 PetscErrorCode ierr; 3424 3425 PetscFunctionBegin; 3426 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 3427 ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 3428 if (subdm) {(*subdm)->useNatural = dm->useNatural;} 3429 if (dm->useNatural && dm->sfMigration) { 3430 PetscSF sfMigrationInv,sfNatural; 3431 PetscSection section, sectionSeq; 3432 3433 (*subdm)->sfMigration = dm->sfMigration; 3434 ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr); 3435 ierr = DMGetLocalSection((*subdm), §ion);CHKERRQ(ierr); 3436 ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3437 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq);CHKERRQ(ierr); 3438 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3439 3440 ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3441 (*subdm)->sfNatural = sfNatural; 3442 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3443 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3444 } 3445 PetscFunctionReturn(0); 3446 } 3447 3448 PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 3449 { 3450 PetscErrorCode ierr; 3451 PetscInt i = 0; 3452 3453 PetscFunctionBegin; 3454 ierr = DMClone(dms[0], superdm);CHKERRQ(ierr); 3455 ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr); 3456 (*superdm)->useNatural = PETSC_FALSE; 3457 for (i = 0; i < len; i++) { 3458 if (dms[i]->useNatural && dms[i]->sfMigration) { 3459 PetscSF sfMigrationInv,sfNatural; 3460 PetscSection section, sectionSeq; 3461 3462 (*superdm)->sfMigration = dms[i]->sfMigration; 3463 ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr); 3464 (*superdm)->useNatural = PETSC_TRUE; 3465 ierr = DMGetLocalSection((*superdm), §ion);CHKERRQ(ierr); 3466 ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 3467 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq);CHKERRQ(ierr); 3468 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 3469 3470 ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 3471 (*superdm)->sfNatural = sfNatural; 3472 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 3473 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 3474 break; 3475 } 3476 } 3477 PetscFunctionReturn(0); 3478 } 3479 3480 /*@ 3481 DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 3482 3483 Not collective 3484 3485 Input Parameter: 3486 . mesh - The DMPlex 3487 3488 Output Parameter: 3489 3490 Note: 3491 This should be called after all calls to DMPlexSetCone() 3492 3493 Level: beginner 3494 3495 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 3496 @*/ 3497 PetscErrorCode DMPlexSymmetrize(DM dm) 3498 { 3499 DM_Plex *mesh = (DM_Plex*) dm->data; 3500 PetscInt *offsets; 3501 PetscInt supportSize; 3502 PetscInt pStart, pEnd, p; 3503 PetscErrorCode ierr; 3504 3505 PetscFunctionBegin; 3506 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3507 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 3508 ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3509 /* Calculate support sizes */ 3510 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3511 for (p = pStart; p < pEnd; ++p) { 3512 PetscInt dof, off, c; 3513 3514 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3515 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3516 for (c = off; c < off+dof; ++c) { 3517 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 3518 } 3519 } 3520 for (p = pStart; p < pEnd; ++p) { 3521 PetscInt dof; 3522 3523 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 3524 3525 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 3526 } 3527 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 3528 /* Calculate supports */ 3529 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 3530 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 3531 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 3532 for (p = pStart; p < pEnd; ++p) { 3533 PetscInt dof, off, c; 3534 3535 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 3536 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 3537 for (c = off; c < off+dof; ++c) { 3538 const PetscInt q = mesh->cones[c]; 3539 PetscInt offS; 3540 3541 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 3542 3543 mesh->supports[offS+offsets[q]] = p; 3544 ++offsets[q]; 3545 } 3546 } 3547 ierr = PetscFree(offsets);CHKERRQ(ierr); 3548 ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 3549 PetscFunctionReturn(0); 3550 } 3551 3552 static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 3553 { 3554 IS stratumIS; 3555 PetscErrorCode ierr; 3556 3557 PetscFunctionBegin; 3558 if (pStart >= pEnd) PetscFunctionReturn(0); 3559 if (PetscDefined(USE_DEBUG)) { 3560 PetscInt qStart, qEnd, numLevels, level; 3561 PetscBool overlap = PETSC_FALSE; 3562 ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr); 3563 for (level = 0; level < numLevels; level++) { 3564 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3565 if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 3566 } 3567 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); 3568 } 3569 ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr); 3570 ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr); 3571 ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 3572 PetscFunctionReturn(0); 3573 } 3574 3575 /*@ 3576 DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 3577 can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 3578 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 3579 the DAG. 3580 3581 Collective on dm 3582 3583 Input Parameter: 3584 . mesh - The DMPlex 3585 3586 Output Parameter: 3587 3588 Notes: 3589 Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 3590 meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 3591 until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 3592 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 3593 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 3594 3595 The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 3596 if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 3597 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 3598 to interpolate only that one (e0), so that 3599 $ cone(c0) = {e0, v2} 3600 $ cone(e0) = {v0, v1} 3601 If DMPlexStratify() is run on this mesh, it will give depths 3602 $ depth 0 = {v0, v1, v2} 3603 $ depth 1 = {e0, c0} 3604 where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 3605 3606 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 3607 3608 Level: beginner 3609 3610 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes() 3611 @*/ 3612 PetscErrorCode DMPlexStratify(DM dm) 3613 { 3614 DM_Plex *mesh = (DM_Plex*) dm->data; 3615 DMLabel label; 3616 PetscInt pStart, pEnd, p; 3617 PetscInt numRoots = 0, numLeaves = 0; 3618 PetscErrorCode ierr; 3619 3620 PetscFunctionBegin; 3621 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3622 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3623 3624 /* Create depth label */ 3625 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3626 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 3627 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3628 3629 { 3630 /* Initialize roots and count leaves */ 3631 PetscInt sMin = PETSC_MAX_INT; 3632 PetscInt sMax = PETSC_MIN_INT; 3633 PetscInt coneSize, supportSize; 3634 3635 for (p = pStart; p < pEnd; ++p) { 3636 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3637 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3638 if (!coneSize && supportSize) { 3639 sMin = PetscMin(p, sMin); 3640 sMax = PetscMax(p, sMax); 3641 ++numRoots; 3642 } else if (!supportSize && coneSize) { 3643 ++numLeaves; 3644 } else if (!supportSize && !coneSize) { 3645 /* Isolated points */ 3646 sMin = PetscMin(p, sMin); 3647 sMax = PetscMax(p, sMax); 3648 } 3649 } 3650 ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr); 3651 } 3652 3653 if (numRoots + numLeaves == (pEnd - pStart)) { 3654 PetscInt sMin = PETSC_MAX_INT; 3655 PetscInt sMax = PETSC_MIN_INT; 3656 PetscInt coneSize, supportSize; 3657 3658 for (p = pStart; p < pEnd; ++p) { 3659 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3660 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 3661 if (!supportSize && coneSize) { 3662 sMin = PetscMin(p, sMin); 3663 sMax = PetscMax(p, sMax); 3664 } 3665 } 3666 ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr); 3667 } else { 3668 PetscInt level = 0; 3669 PetscInt qStart, qEnd, q; 3670 3671 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3672 while (qEnd > qStart) { 3673 PetscInt sMin = PETSC_MAX_INT; 3674 PetscInt sMax = PETSC_MIN_INT; 3675 3676 for (q = qStart; q < qEnd; ++q) { 3677 const PetscInt *support; 3678 PetscInt supportSize, s; 3679 3680 ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr); 3681 ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr); 3682 for (s = 0; s < supportSize; ++s) { 3683 sMin = PetscMin(support[s], sMin); 3684 sMax = PetscMax(support[s], sMax); 3685 } 3686 } 3687 ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr); 3688 ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr); 3689 ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 3690 } 3691 } 3692 { /* just in case there is an empty process */ 3693 PetscInt numValues, maxValues = 0, v; 3694 3695 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 3696 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 3697 for (v = numValues; v < maxValues; v++) { 3698 ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr); 3699 } 3700 } 3701 ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr); 3702 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 3703 PetscFunctionReturn(0); 3704 } 3705 3706 PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 3707 { 3708 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3709 PetscInt dim, depth, pheight, coneSize; 3710 PetscErrorCode ierr; 3711 3712 PetscFunctionBeginHot; 3713 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3714 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3715 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 3716 pheight = depth - pdepth; 3717 if (depth <= 1) { 3718 switch (pdepth) { 3719 case 0: ct = DM_POLYTOPE_POINT;break; 3720 case 1: 3721 switch (coneSize) { 3722 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3723 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3724 case 4: 3725 switch (dim) { 3726 case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 3727 case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 3728 default: break; 3729 } 3730 break; 3731 case 5: ct = DM_POLYTOPE_PYRAMID;break; 3732 case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3733 case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 3734 default: break; 3735 } 3736 } 3737 } else { 3738 if (pdepth == 0) { 3739 ct = DM_POLYTOPE_POINT; 3740 } else if (pheight == 0) { 3741 switch (dim) { 3742 case 1: 3743 switch (coneSize) { 3744 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3745 default: break; 3746 } 3747 break; 3748 case 2: 3749 switch (coneSize) { 3750 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3751 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3752 default: break; 3753 } 3754 break; 3755 case 3: 3756 switch (coneSize) { 3757 case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 3758 case 5: 3759 { 3760 const PetscInt *cone; 3761 PetscInt faceConeSize; 3762 3763 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 3764 ierr = DMPlexGetConeSize(dm, cone[0], &faceConeSize);CHKERRQ(ierr); 3765 switch (faceConeSize) { 3766 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3767 case 4: ct = DM_POLYTOPE_PYRAMID;break; 3768 } 3769 } 3770 break; 3771 case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 3772 default: break; 3773 } 3774 break; 3775 default: break; 3776 } 3777 } else if (pheight > 0) { 3778 switch (coneSize) { 3779 case 2: ct = DM_POLYTOPE_SEGMENT;break; 3780 case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3781 case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3782 default: break; 3783 } 3784 } 3785 } 3786 *pt = ct; 3787 PetscFunctionReturn(0); 3788 } 3789 3790 /*@ 3791 DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 3792 3793 Collective on dm 3794 3795 Input Parameter: 3796 . mesh - The DMPlex 3797 3798 DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 3799 3800 Level: developer 3801 3802 Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 3803 internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 3804 automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 3805 3806 .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel() 3807 @*/ 3808 PetscErrorCode DMPlexComputeCellTypes(DM dm) 3809 { 3810 DM_Plex *mesh; 3811 DMLabel ctLabel; 3812 PetscInt pStart, pEnd, p; 3813 PetscErrorCode ierr; 3814 3815 PetscFunctionBegin; 3816 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3817 mesh = (DM_Plex *) dm->data; 3818 ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr); 3819 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 3820 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3821 for (p = pStart; p < pEnd; ++p) { 3822 DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3823 PetscInt pdepth; 3824 3825 ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr); 3826 ierr = DMPlexComputeCellType_Internal(dm, p, pdepth, &ct);CHKERRQ(ierr); 3827 if (ct == DM_POLYTOPE_UNKNOWN) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p); 3828 ierr = DMLabelSetValue(ctLabel, p, ct);CHKERRQ(ierr); 3829 } 3830 ierr = PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState);CHKERRQ(ierr); 3831 ierr = PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr); 3832 PetscFunctionReturn(0); 3833 } 3834 3835 /*@C 3836 DMPlexGetJoin - Get an array for the join of the set of points 3837 3838 Not Collective 3839 3840 Input Parameters: 3841 + dm - The DMPlex object 3842 . numPoints - The number of input points for the join 3843 - points - The input points 3844 3845 Output Parameters: 3846 + numCoveredPoints - The number of points in the join 3847 - coveredPoints - The points in the join 3848 3849 Level: intermediate 3850 3851 Note: Currently, this is restricted to a single level join 3852 3853 Fortran Notes: 3854 Since it returns an array, this routine is only available in Fortran 90, and you must 3855 include petsc.h90 in your code. 3856 3857 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3858 3859 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 3860 @*/ 3861 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3862 { 3863 DM_Plex *mesh = (DM_Plex*) dm->data; 3864 PetscInt *join[2]; 3865 PetscInt joinSize, i = 0; 3866 PetscInt dof, off, p, c, m; 3867 PetscErrorCode ierr; 3868 3869 PetscFunctionBegin; 3870 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3871 PetscValidIntPointer(points, 3); 3872 PetscValidIntPointer(numCoveredPoints, 4); 3873 PetscValidPointer(coveredPoints, 5); 3874 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 3875 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 3876 /* Copy in support of first point */ 3877 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 3878 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 3879 for (joinSize = 0; joinSize < dof; ++joinSize) { 3880 join[i][joinSize] = mesh->supports[off+joinSize]; 3881 } 3882 /* Check each successive support */ 3883 for (p = 1; p < numPoints; ++p) { 3884 PetscInt newJoinSize = 0; 3885 3886 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 3887 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 3888 for (c = 0; c < dof; ++c) { 3889 const PetscInt point = mesh->supports[off+c]; 3890 3891 for (m = 0; m < joinSize; ++m) { 3892 if (point == join[i][m]) { 3893 join[1-i][newJoinSize++] = point; 3894 break; 3895 } 3896 } 3897 } 3898 joinSize = newJoinSize; 3899 i = 1-i; 3900 } 3901 *numCoveredPoints = joinSize; 3902 *coveredPoints = join[i]; 3903 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 3904 PetscFunctionReturn(0); 3905 } 3906 3907 /*@C 3908 DMPlexRestoreJoin - Restore an array for the join of the set of points 3909 3910 Not Collective 3911 3912 Input Parameters: 3913 + dm - The DMPlex object 3914 . numPoints - The number of input points for the join 3915 - points - The input points 3916 3917 Output Parameters: 3918 + numCoveredPoints - The number of points in the join 3919 - coveredPoints - The points in the join 3920 3921 Fortran Notes: 3922 Since it returns an array, this routine is only available in Fortran 90, and you must 3923 include petsc.h90 in your code. 3924 3925 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3926 3927 Level: intermediate 3928 3929 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 3930 @*/ 3931 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3932 { 3933 PetscErrorCode ierr; 3934 3935 PetscFunctionBegin; 3936 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3937 if (points) PetscValidIntPointer(points,3); 3938 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 3939 PetscValidPointer(coveredPoints, 5); 3940 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 3941 if (numCoveredPoints) *numCoveredPoints = 0; 3942 PetscFunctionReturn(0); 3943 } 3944 3945 /*@C 3946 DMPlexGetFullJoin - Get an array for the join of the set of points 3947 3948 Not Collective 3949 3950 Input Parameters: 3951 + dm - The DMPlex object 3952 . numPoints - The number of input points for the join 3953 - points - The input points 3954 3955 Output Parameters: 3956 + numCoveredPoints - The number of points in the join 3957 - coveredPoints - The points in the join 3958 3959 Fortran Notes: 3960 Since it returns an array, this routine is only available in Fortran 90, and you must 3961 include petsc.h90 in your code. 3962 3963 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 3964 3965 Level: intermediate 3966 3967 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 3968 @*/ 3969 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3970 { 3971 DM_Plex *mesh = (DM_Plex*) dm->data; 3972 PetscInt *offsets, **closures; 3973 PetscInt *join[2]; 3974 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 3975 PetscInt p, d, c, m, ms; 3976 PetscErrorCode ierr; 3977 3978 PetscFunctionBegin; 3979 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3980 PetscValidIntPointer(points, 3); 3981 PetscValidIntPointer(numCoveredPoints, 4); 3982 PetscValidPointer(coveredPoints, 5); 3983 3984 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3985 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 3986 ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 3987 ms = mesh->maxSupportSize; 3988 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 3989 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 3990 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 3991 3992 for (p = 0; p < numPoints; ++p) { 3993 PetscInt closureSize; 3994 3995 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 3996 3997 offsets[p*(depth+2)+0] = 0; 3998 for (d = 0; d < depth+1; ++d) { 3999 PetscInt pStart, pEnd, i; 4000 4001 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 4002 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 4003 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4004 offsets[p*(depth+2)+d+1] = i; 4005 break; 4006 } 4007 } 4008 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 4009 } 4010 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); 4011 } 4012 for (d = 0; d < depth+1; ++d) { 4013 PetscInt dof; 4014 4015 /* Copy in support of first point */ 4016 dof = offsets[d+1] - offsets[d]; 4017 for (joinSize = 0; joinSize < dof; ++joinSize) { 4018 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 4019 } 4020 /* Check each successive cone */ 4021 for (p = 1; p < numPoints && joinSize; ++p) { 4022 PetscInt newJoinSize = 0; 4023 4024 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 4025 for (c = 0; c < dof; ++c) { 4026 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 4027 4028 for (m = 0; m < joinSize; ++m) { 4029 if (point == join[i][m]) { 4030 join[1-i][newJoinSize++] = point; 4031 break; 4032 } 4033 } 4034 } 4035 joinSize = newJoinSize; 4036 i = 1-i; 4037 } 4038 if (joinSize) break; 4039 } 4040 *numCoveredPoints = joinSize; 4041 *coveredPoints = join[i]; 4042 for (p = 0; p < numPoints; ++p) { 4043 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 4044 } 4045 ierr = PetscFree(closures);CHKERRQ(ierr); 4046 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4047 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 4048 PetscFunctionReturn(0); 4049 } 4050 4051 /*@C 4052 DMPlexGetMeet - Get an array for the meet of the set of points 4053 4054 Not Collective 4055 4056 Input Parameters: 4057 + dm - The DMPlex object 4058 . numPoints - The number of input points for the meet 4059 - points - The input points 4060 4061 Output Parameters: 4062 + numCoveredPoints - The number of points in the meet 4063 - coveredPoints - The points in the meet 4064 4065 Level: intermediate 4066 4067 Note: Currently, this is restricted to a single level meet 4068 4069 Fortran Notes: 4070 Since it returns an array, this routine is only available in Fortran 90, and you must 4071 include petsc.h90 in your code. 4072 4073 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4074 4075 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 4076 @*/ 4077 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4078 { 4079 DM_Plex *mesh = (DM_Plex*) dm->data; 4080 PetscInt *meet[2]; 4081 PetscInt meetSize, i = 0; 4082 PetscInt dof, off, p, c, m; 4083 PetscErrorCode ierr; 4084 4085 PetscFunctionBegin; 4086 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4087 PetscValidPointer(points, 3); 4088 PetscValidPointer(numCoveringPoints, 4); 4089 PetscValidPointer(coveringPoints, 5); 4090 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4091 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4092 /* Copy in cone of first point */ 4093 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 4094 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 4095 for (meetSize = 0; meetSize < dof; ++meetSize) { 4096 meet[i][meetSize] = mesh->cones[off+meetSize]; 4097 } 4098 /* Check each successive cone */ 4099 for (p = 1; p < numPoints; ++p) { 4100 PetscInt newMeetSize = 0; 4101 4102 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 4103 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 4104 for (c = 0; c < dof; ++c) { 4105 const PetscInt point = mesh->cones[off+c]; 4106 4107 for (m = 0; m < meetSize; ++m) { 4108 if (point == meet[i][m]) { 4109 meet[1-i][newMeetSize++] = point; 4110 break; 4111 } 4112 } 4113 } 4114 meetSize = newMeetSize; 4115 i = 1-i; 4116 } 4117 *numCoveringPoints = meetSize; 4118 *coveringPoints = meet[i]; 4119 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4120 PetscFunctionReturn(0); 4121 } 4122 4123 /*@C 4124 DMPlexRestoreMeet - Restore an array for the meet of the set of points 4125 4126 Not Collective 4127 4128 Input Parameters: 4129 + dm - The DMPlex object 4130 . numPoints - The number of input points for the meet 4131 - points - The input points 4132 4133 Output Parameters: 4134 + numCoveredPoints - The number of points in the meet 4135 - coveredPoints - The points in the meet 4136 4137 Level: intermediate 4138 4139 Fortran Notes: 4140 Since it returns an array, this routine is only available in Fortran 90, and you must 4141 include petsc.h90 in your code. 4142 4143 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4144 4145 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 4146 @*/ 4147 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4148 { 4149 PetscErrorCode ierr; 4150 4151 PetscFunctionBegin; 4152 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4153 if (points) PetscValidIntPointer(points,3); 4154 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 4155 PetscValidPointer(coveredPoints,5); 4156 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 4157 if (numCoveredPoints) *numCoveredPoints = 0; 4158 PetscFunctionReturn(0); 4159 } 4160 4161 /*@C 4162 DMPlexGetFullMeet - Get an array for the meet of the set of points 4163 4164 Not Collective 4165 4166 Input Parameters: 4167 + dm - The DMPlex object 4168 . numPoints - The number of input points for the meet 4169 - points - The input points 4170 4171 Output Parameters: 4172 + numCoveredPoints - The number of points in the meet 4173 - coveredPoints - The points in the meet 4174 4175 Level: intermediate 4176 4177 Fortran Notes: 4178 Since it returns an array, this routine is only available in Fortran 90, and you must 4179 include petsc.h90 in your code. 4180 4181 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 4182 4183 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 4184 @*/ 4185 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4186 { 4187 DM_Plex *mesh = (DM_Plex*) dm->data; 4188 PetscInt *offsets, **closures; 4189 PetscInt *meet[2]; 4190 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 4191 PetscInt p, h, c, m, mc; 4192 PetscErrorCode ierr; 4193 4194 PetscFunctionBegin; 4195 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4196 PetscValidPointer(points, 3); 4197 PetscValidPointer(numCoveredPoints, 4); 4198 PetscValidPointer(coveredPoints, 5); 4199 4200 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 4201 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 4202 ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4203 mc = mesh->maxConeSize; 4204 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 4205 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 4206 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 4207 4208 for (p = 0; p < numPoints; ++p) { 4209 PetscInt closureSize; 4210 4211 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 4212 4213 offsets[p*(height+2)+0] = 0; 4214 for (h = 0; h < height+1; ++h) { 4215 PetscInt pStart, pEnd, i; 4216 4217 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 4218 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 4219 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 4220 offsets[p*(height+2)+h+1] = i; 4221 break; 4222 } 4223 } 4224 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 4225 } 4226 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); 4227 } 4228 for (h = 0; h < height+1; ++h) { 4229 PetscInt dof; 4230 4231 /* Copy in cone of first point */ 4232 dof = offsets[h+1] - offsets[h]; 4233 for (meetSize = 0; meetSize < dof; ++meetSize) { 4234 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 4235 } 4236 /* Check each successive cone */ 4237 for (p = 1; p < numPoints && meetSize; ++p) { 4238 PetscInt newMeetSize = 0; 4239 4240 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 4241 for (c = 0; c < dof; ++c) { 4242 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 4243 4244 for (m = 0; m < meetSize; ++m) { 4245 if (point == meet[i][m]) { 4246 meet[1-i][newMeetSize++] = point; 4247 break; 4248 } 4249 } 4250 } 4251 meetSize = newMeetSize; 4252 i = 1-i; 4253 } 4254 if (meetSize) break; 4255 } 4256 *numCoveredPoints = meetSize; 4257 *coveredPoints = meet[i]; 4258 for (p = 0; p < numPoints; ++p) { 4259 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 4260 } 4261 ierr = PetscFree(closures);CHKERRQ(ierr); 4262 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 4263 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 4264 PetscFunctionReturn(0); 4265 } 4266 4267 /*@C 4268 DMPlexEqual - Determine if two DMs have the same topology 4269 4270 Not Collective 4271 4272 Input Parameters: 4273 + dmA - A DMPlex object 4274 - dmB - A DMPlex object 4275 4276 Output Parameters: 4277 . equal - PETSC_TRUE if the topologies are identical 4278 4279 Level: intermediate 4280 4281 Notes: 4282 We are not solving graph isomorphism, so we do not permutation. 4283 4284 .seealso: DMPlexGetCone() 4285 @*/ 4286 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 4287 { 4288 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 4289 PetscErrorCode ierr; 4290 4291 PetscFunctionBegin; 4292 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 4293 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 4294 PetscValidPointer(equal, 3); 4295 4296 *equal = PETSC_FALSE; 4297 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 4298 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 4299 if (depth != depthB) PetscFunctionReturn(0); 4300 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 4301 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 4302 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 4303 for (p = pStart; p < pEnd; ++p) { 4304 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 4305 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 4306 4307 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 4308 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 4309 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 4310 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 4311 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 4312 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 4313 if (coneSize != coneSizeB) PetscFunctionReturn(0); 4314 for (c = 0; c < coneSize; ++c) { 4315 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 4316 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 4317 } 4318 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 4319 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 4320 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 4321 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 4322 if (supportSize != supportSizeB) PetscFunctionReturn(0); 4323 for (s = 0; s < supportSize; ++s) { 4324 if (support[s] != supportB[s]) PetscFunctionReturn(0); 4325 } 4326 } 4327 *equal = PETSC_TRUE; 4328 PetscFunctionReturn(0); 4329 } 4330 4331 /*@C 4332 DMPlexGetNumFaceVertices - Returns the number of vertices on a face 4333 4334 Not Collective 4335 4336 Input Parameters: 4337 + dm - The DMPlex 4338 . cellDim - The cell dimension 4339 - numCorners - The number of vertices on a cell 4340 4341 Output Parameters: 4342 . numFaceVertices - The number of vertices on a face 4343 4344 Level: developer 4345 4346 Notes: 4347 Of course this can only work for a restricted set of symmetric shapes 4348 4349 .seealso: DMPlexGetCone() 4350 @*/ 4351 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 4352 { 4353 MPI_Comm comm; 4354 PetscErrorCode ierr; 4355 4356 PetscFunctionBegin; 4357 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4358 PetscValidPointer(numFaceVertices,4); 4359 switch (cellDim) { 4360 case 0: 4361 *numFaceVertices = 0; 4362 break; 4363 case 1: 4364 *numFaceVertices = 1; 4365 break; 4366 case 2: 4367 switch (numCorners) { 4368 case 3: /* triangle */ 4369 *numFaceVertices = 2; /* Edge has 2 vertices */ 4370 break; 4371 case 4: /* quadrilateral */ 4372 *numFaceVertices = 2; /* Edge has 2 vertices */ 4373 break; 4374 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 4375 *numFaceVertices = 3; /* Edge has 3 vertices */ 4376 break; 4377 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 4378 *numFaceVertices = 3; /* Edge has 3 vertices */ 4379 break; 4380 default: 4381 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4382 } 4383 break; 4384 case 3: 4385 switch (numCorners) { 4386 case 4: /* tetradehdron */ 4387 *numFaceVertices = 3; /* Face has 3 vertices */ 4388 break; 4389 case 6: /* tet cohesive cells */ 4390 *numFaceVertices = 4; /* Face has 4 vertices */ 4391 break; 4392 case 8: /* hexahedron */ 4393 *numFaceVertices = 4; /* Face has 4 vertices */ 4394 break; 4395 case 9: /* tet cohesive Lagrange cells */ 4396 *numFaceVertices = 6; /* Face has 6 vertices */ 4397 break; 4398 case 10: /* quadratic tetrahedron */ 4399 *numFaceVertices = 6; /* Face has 6 vertices */ 4400 break; 4401 case 12: /* hex cohesive Lagrange cells */ 4402 *numFaceVertices = 6; /* Face has 6 vertices */ 4403 break; 4404 case 18: /* quadratic tet cohesive Lagrange cells */ 4405 *numFaceVertices = 6; /* Face has 6 vertices */ 4406 break; 4407 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 4408 *numFaceVertices = 9; /* Face has 9 vertices */ 4409 break; 4410 default: 4411 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 4412 } 4413 break; 4414 default: 4415 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 4416 } 4417 PetscFunctionReturn(0); 4418 } 4419 4420 /*@ 4421 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 4422 4423 Not Collective 4424 4425 Input Parameter: 4426 . dm - The DMPlex object 4427 4428 Output Parameter: 4429 . depthLabel - The DMLabel recording point depth 4430 4431 Level: developer 4432 4433 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), 4434 @*/ 4435 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 4436 { 4437 PetscFunctionBegin; 4438 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4439 PetscValidPointer(depthLabel, 2); 4440 *depthLabel = dm->depthLabel; 4441 PetscFunctionReturn(0); 4442 } 4443 4444 /*@ 4445 DMPlexGetDepth - Get the depth of the DAG representing this mesh 4446 4447 Not Collective 4448 4449 Input Parameter: 4450 . dm - The DMPlex object 4451 4452 Output Parameter: 4453 . depth - The number of strata (breadth first levels) in the DAG 4454 4455 Level: developer 4456 4457 Notes: 4458 This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 4459 The point depth is described more in detail in DMPlexGetDepthStratum(). 4460 An empty mesh gives -1. 4461 4462 .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize() 4463 @*/ 4464 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 4465 { 4466 DMLabel label; 4467 PetscInt d = 0; 4468 PetscErrorCode ierr; 4469 4470 PetscFunctionBegin; 4471 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4472 PetscValidPointer(depth, 2); 4473 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4474 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 4475 *depth = d-1; 4476 PetscFunctionReturn(0); 4477 } 4478 4479 /*@ 4480 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 4481 4482 Not Collective 4483 4484 Input Parameters: 4485 + dm - The DMPlex object 4486 - stratumValue - The requested depth 4487 4488 Output Parameters: 4489 + start - The first point at this depth 4490 - end - One beyond the last point at this depth 4491 4492 Notes: 4493 Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 4494 often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 4495 higher dimension, e.g., "edges". 4496 4497 Level: developer 4498 4499 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate() 4500 @*/ 4501 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4502 { 4503 DMLabel label; 4504 PetscInt pStart, pEnd; 4505 PetscErrorCode ierr; 4506 4507 PetscFunctionBegin; 4508 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4509 if (start) {PetscValidPointer(start, 3); *start = 0;} 4510 if (end) {PetscValidPointer(end, 4); *end = 0;} 4511 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4512 if (pStart == pEnd) PetscFunctionReturn(0); 4513 if (stratumValue < 0) { 4514 if (start) *start = pStart; 4515 if (end) *end = pEnd; 4516 PetscFunctionReturn(0); 4517 } 4518 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4519 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4520 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 4521 PetscFunctionReturn(0); 4522 } 4523 4524 /*@ 4525 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 4526 4527 Not Collective 4528 4529 Input Parameters: 4530 + dm - The DMPlex object 4531 - stratumValue - The requested height 4532 4533 Output Parameters: 4534 + start - The first point at this height 4535 - end - One beyond the last point at this height 4536 4537 Notes: 4538 Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 4539 points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 4540 stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 4541 4542 Level: developer 4543 4544 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight() 4545 @*/ 4546 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 4547 { 4548 DMLabel label; 4549 PetscInt depth, pStart, pEnd; 4550 PetscErrorCode ierr; 4551 4552 PetscFunctionBegin; 4553 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4554 if (start) {PetscValidPointer(start, 3); *start = 0;} 4555 if (end) {PetscValidPointer(end, 4); *end = 0;} 4556 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4557 if (pStart == pEnd) PetscFunctionReturn(0); 4558 if (stratumValue < 0) { 4559 if (start) *start = pStart; 4560 if (end) *end = pEnd; 4561 PetscFunctionReturn(0); 4562 } 4563 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4564 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 4565 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 4566 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 4567 PetscFunctionReturn(0); 4568 } 4569 4570 /*@ 4571 DMPlexGetPointDepth - Get the depth of a given point 4572 4573 Not Collective 4574 4575 Input Parameter: 4576 + dm - The DMPlex object 4577 - point - The point 4578 4579 Output Parameter: 4580 . depth - The depth of the point 4581 4582 Level: intermediate 4583 4584 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight() 4585 @*/ 4586 PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 4587 { 4588 PetscErrorCode ierr; 4589 4590 PetscFunctionBegin; 4591 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4592 PetscValidIntPointer(depth, 3); 4593 ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr); 4594 PetscFunctionReturn(0); 4595 } 4596 4597 /*@ 4598 DMPlexGetPointHeight - Get the height of a given point 4599 4600 Not Collective 4601 4602 Input Parameter: 4603 + dm - The DMPlex object 4604 - point - The point 4605 4606 Output Parameter: 4607 . height - The height of the point 4608 4609 Level: intermediate 4610 4611 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth() 4612 @*/ 4613 PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 4614 { 4615 PetscInt n, pDepth; 4616 PetscErrorCode ierr; 4617 4618 PetscFunctionBegin; 4619 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4620 PetscValidIntPointer(height, 3); 4621 ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr); 4622 ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr); 4623 *height = n - 1 - pDepth; /* DAG depth is n-1 */ 4624 PetscFunctionReturn(0); 4625 } 4626 4627 /*@ 4628 DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 4629 4630 Not Collective 4631 4632 Input Parameter: 4633 . dm - The DMPlex object 4634 4635 Output Parameter: 4636 . celltypeLabel - The DMLabel recording cell polytope type 4637 4638 Note: This function will trigger automatica computation of cell types. This can be disabled by calling 4639 DMCreateLabel(dm, "celltype") beforehand. 4640 4641 Level: developer 4642 4643 .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel() 4644 @*/ 4645 PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 4646 { 4647 PetscErrorCode ierr; 4648 4649 PetscFunctionBegin; 4650 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4651 PetscValidPointer(celltypeLabel, 2); 4652 if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);} 4653 *celltypeLabel = dm->celltypeLabel; 4654 PetscFunctionReturn(0); 4655 } 4656 4657 /*@ 4658 DMPlexGetCellType - Get the polytope type of a given cell 4659 4660 Not Collective 4661 4662 Input Parameter: 4663 + dm - The DMPlex object 4664 - cell - The cell 4665 4666 Output Parameter: 4667 . celltype - The polytope type of the cell 4668 4669 Level: intermediate 4670 4671 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth() 4672 @*/ 4673 PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 4674 { 4675 DMLabel label; 4676 PetscInt ct; 4677 PetscErrorCode ierr; 4678 4679 PetscFunctionBegin; 4680 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4681 PetscValidPointer(celltype, 3); 4682 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4683 ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr); 4684 if (ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell); 4685 *celltype = (DMPolytopeType) ct; 4686 PetscFunctionReturn(0); 4687 } 4688 4689 /*@ 4690 DMPlexSetCellType - Set the polytope type of a given cell 4691 4692 Not Collective 4693 4694 Input Parameters: 4695 + dm - The DMPlex object 4696 . cell - The cell 4697 - celltype - The polytope type of the cell 4698 4699 Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 4700 is executed. This function will override the computed type. However, if automatic classification will not succeed 4701 and a user wants to manually specify all types, the classification must be disabled by calling 4702 DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 4703 4704 Level: advanced 4705 4706 .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel() 4707 @*/ 4708 PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 4709 { 4710 DMLabel label; 4711 PetscErrorCode ierr; 4712 4713 PetscFunctionBegin; 4714 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4715 ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 4716 ierr = DMLabelSetValue(label, cell, celltype);CHKERRQ(ierr); 4717 PetscFunctionReturn(0); 4718 } 4719 4720 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 4721 { 4722 PetscSection section, s; 4723 Mat m; 4724 PetscInt maxHeight; 4725 PetscErrorCode ierr; 4726 4727 PetscFunctionBegin; 4728 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 4729 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 4730 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 4731 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 4732 ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr); 4733 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 4734 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 4735 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 4736 ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr); 4737 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 4738 ierr = MatDestroy(&m);CHKERRQ(ierr); 4739 4740 ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr); 4741 ierr = DMCreateDS(*cdm);CHKERRQ(ierr); 4742 PetscFunctionReturn(0); 4743 } 4744 4745 PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 4746 { 4747 Vec coordsLocal; 4748 DM coordsDM; 4749 PetscErrorCode ierr; 4750 4751 PetscFunctionBegin; 4752 *field = NULL; 4753 ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr); 4754 ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr); 4755 if (coordsLocal && coordsDM) { 4756 ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr); 4757 } 4758 PetscFunctionReturn(0); 4759 } 4760 4761 /*@C 4762 DMPlexGetConeSection - Return a section which describes the layout of cone data 4763 4764 Not Collective 4765 4766 Input Parameters: 4767 . dm - The DMPlex object 4768 4769 Output Parameter: 4770 . section - The PetscSection object 4771 4772 Level: developer 4773 4774 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 4775 @*/ 4776 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 4777 { 4778 DM_Plex *mesh = (DM_Plex*) dm->data; 4779 4780 PetscFunctionBegin; 4781 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4782 if (section) *section = mesh->coneSection; 4783 PetscFunctionReturn(0); 4784 } 4785 4786 /*@C 4787 DMPlexGetSupportSection - Return a section which describes the layout of support data 4788 4789 Not Collective 4790 4791 Input Parameters: 4792 . dm - The DMPlex object 4793 4794 Output Parameter: 4795 . section - The PetscSection object 4796 4797 Level: developer 4798 4799 .seealso: DMPlexGetConeSection() 4800 @*/ 4801 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 4802 { 4803 DM_Plex *mesh = (DM_Plex*) dm->data; 4804 4805 PetscFunctionBegin; 4806 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4807 if (section) *section = mesh->supportSection; 4808 PetscFunctionReturn(0); 4809 } 4810 4811 /*@C 4812 DMPlexGetCones - Return cone data 4813 4814 Not Collective 4815 4816 Input Parameters: 4817 . dm - The DMPlex object 4818 4819 Output Parameter: 4820 . cones - The cone for each point 4821 4822 Level: developer 4823 4824 .seealso: DMPlexGetConeSection() 4825 @*/ 4826 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 4827 { 4828 DM_Plex *mesh = (DM_Plex*) dm->data; 4829 4830 PetscFunctionBegin; 4831 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4832 if (cones) *cones = mesh->cones; 4833 PetscFunctionReturn(0); 4834 } 4835 4836 /*@C 4837 DMPlexGetConeOrientations - Return cone orientation data 4838 4839 Not Collective 4840 4841 Input Parameters: 4842 . dm - The DMPlex object 4843 4844 Output Parameter: 4845 . coneOrientations - The cone orientation for each point 4846 4847 Level: developer 4848 4849 .seealso: DMPlexGetConeSection() 4850 @*/ 4851 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 4852 { 4853 DM_Plex *mesh = (DM_Plex*) dm->data; 4854 4855 PetscFunctionBegin; 4856 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4857 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 4858 PetscFunctionReturn(0); 4859 } 4860 4861 /******************************** FEM Support **********************************/ 4862 4863 /* 4864 Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 4865 representing a line in the section. 4866 */ 4867 static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 4868 { 4869 PetscErrorCode ierr; 4870 4871 PetscFunctionBeginHot; 4872 ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr); 4873 if (line < 0) { 4874 *k = 0; 4875 *Nc = 0; 4876 } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 4877 *k = 1; 4878 } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 4879 /* An order k SEM disc has k-1 dofs on an edge */ 4880 ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr); 4881 *k = *k / *Nc + 1; 4882 } 4883 PetscFunctionReturn(0); 4884 } 4885 4886 /*@ 4887 4888 DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 4889 lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 4890 section provided (or the section of the DM). 4891 4892 Input Parameters: 4893 + dm - The DM 4894 . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 4895 - section - The PetscSection to reorder, or NULL for the default section 4896 4897 Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 4898 degree of the basis. 4899 4900 Example: 4901 A typical interpolated single-quad mesh might order points as 4902 .vb 4903 [c0, v1, v2, v3, v4, e5, e6, e7, e8] 4904 4905 v4 -- e6 -- v3 4906 | | 4907 e7 c0 e8 4908 | | 4909 v1 -- e5 -- v2 4910 .ve 4911 4912 (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 4913 dofs in the order of points, e.g., 4914 .vb 4915 c0 -> [0,1,2,3] 4916 v1 -> [4] 4917 ... 4918 e5 -> [8, 9] 4919 .ve 4920 4921 which corresponds to the dofs 4922 .vb 4923 6 10 11 7 4924 13 2 3 15 4925 12 0 1 14 4926 4 8 9 5 4927 .ve 4928 4929 The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 4930 .vb 4931 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 4932 .ve 4933 4934 After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 4935 .vb 4936 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 4937 .ve 4938 4939 Level: developer 4940 4941 .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection() 4942 @*/ 4943 PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 4944 { 4945 DMLabel label; 4946 PetscInt dim, depth = -1, eStart = -1, Nf; 4947 PetscBool vertexchart; 4948 PetscErrorCode ierr; 4949 4950 PetscFunctionBegin; 4951 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4952 if (dim < 1) PetscFunctionReturn(0); 4953 if (point < 0) { 4954 PetscInt sStart,sEnd; 4955 4956 ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr); 4957 point = sEnd-sStart ? sStart : point; 4958 } 4959 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4960 if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); } 4961 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 4962 if (depth == 1) {eStart = point;} 4963 else if (depth == dim) { 4964 const PetscInt *cone; 4965 4966 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4967 if (dim == 2) eStart = cone[0]; 4968 else if (dim == 3) { 4969 const PetscInt *cone2; 4970 ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 4971 eStart = cone2[0]; 4972 } 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); 4973 } 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); 4974 { /* Determine whether the chart covers all points or just vertices. */ 4975 PetscInt pStart,pEnd,cStart,cEnd; 4976 ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr); 4977 ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr); 4978 if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Just vertices */ 4979 else vertexchart = PETSC_FALSE; /* Assume all interpolated points are in chart */ 4980 } 4981 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 4982 for (PetscInt d=1; d<=dim; d++) { 4983 PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 4984 PetscInt *perm; 4985 4986 for (f = 0; f < Nf; ++f) { 4987 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 4988 size += PetscPowInt(k+1, d)*Nc; 4989 } 4990 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 4991 for (f = 0; f < Nf; ++f) { 4992 switch (d) { 4993 case 1: 4994 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 4995 /* 4996 Original ordering is [ edge of length k-1; vtx0; vtx1 ] 4997 We want [ vtx0; edge of length k-1; vtx1 ] 4998 */ 4999 for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 5000 for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 5001 for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 5002 foffset = offset; 5003 break; 5004 case 2: 5005 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 5006 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5007 /* The SEM order is 5008 5009 v_lb, {e_b}, v_rb, 5010 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 5011 v_lt, reverse {e_t}, v_rt 5012 */ 5013 { 5014 const PetscInt of = 0; 5015 const PetscInt oeb = of + PetscSqr(k-1); 5016 const PetscInt oer = oeb + (k-1); 5017 const PetscInt oet = oer + (k-1); 5018 const PetscInt oel = oet + (k-1); 5019 const PetscInt ovlb = oel + (k-1); 5020 const PetscInt ovrb = ovlb + 1; 5021 const PetscInt ovrt = ovrb + 1; 5022 const PetscInt ovlt = ovrt + 1; 5023 PetscInt o; 5024 5025 /* bottom */ 5026 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 5027 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5028 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 5029 /* middle */ 5030 for (i = 0; i < k-1; ++i) { 5031 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 5032 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; 5033 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 5034 } 5035 /* top */ 5036 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 5037 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5038 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 5039 foffset = offset; 5040 } 5041 break; 5042 case 3: 5043 /* The original hex closure is 5044 5045 {c, 5046 f_b, f_t, f_f, f_b, f_r, f_l, 5047 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 5048 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 5049 */ 5050 ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 5051 /* The SEM order is 5052 Bottom Slice 5053 v_blf, {e^{(k-1)-n}_bf}, v_brf, 5054 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 5055 v_blb, {e_bb}, v_brb, 5056 5057 Middle Slice (j) 5058 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 5059 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 5060 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 5061 5062 Top Slice 5063 v_tlf, {e_tf}, v_trf, 5064 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 5065 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 5066 */ 5067 { 5068 const PetscInt oc = 0; 5069 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 5070 const PetscInt oft = ofb + PetscSqr(k-1); 5071 const PetscInt off = oft + PetscSqr(k-1); 5072 const PetscInt ofk = off + PetscSqr(k-1); 5073 const PetscInt ofr = ofk + PetscSqr(k-1); 5074 const PetscInt ofl = ofr + PetscSqr(k-1); 5075 const PetscInt oebl = ofl + PetscSqr(k-1); 5076 const PetscInt oebb = oebl + (k-1); 5077 const PetscInt oebr = oebb + (k-1); 5078 const PetscInt oebf = oebr + (k-1); 5079 const PetscInt oetf = oebf + (k-1); 5080 const PetscInt oetr = oetf + (k-1); 5081 const PetscInt oetb = oetr + (k-1); 5082 const PetscInt oetl = oetb + (k-1); 5083 const PetscInt oerf = oetl + (k-1); 5084 const PetscInt oelf = oerf + (k-1); 5085 const PetscInt oelb = oelf + (k-1); 5086 const PetscInt oerb = oelb + (k-1); 5087 const PetscInt ovblf = oerb + (k-1); 5088 const PetscInt ovblb = ovblf + 1; 5089 const PetscInt ovbrb = ovblb + 1; 5090 const PetscInt ovbrf = ovbrb + 1; 5091 const PetscInt ovtlf = ovbrf + 1; 5092 const PetscInt ovtrf = ovtlf + 1; 5093 const PetscInt ovtrb = ovtrf + 1; 5094 const PetscInt ovtlb = ovtrb + 1; 5095 PetscInt o, n; 5096 5097 /* Bottom Slice */ 5098 /* bottom */ 5099 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 5100 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5101 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 5102 /* middle */ 5103 for (i = 0; i < k-1; ++i) { 5104 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 5105 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;} 5106 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 5107 } 5108 /* top */ 5109 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 5110 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5111 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 5112 5113 /* Middle Slice */ 5114 for (j = 0; j < k-1; ++j) { 5115 /* bottom */ 5116 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 5117 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; 5118 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 5119 /* middle */ 5120 for (i = 0; i < k-1; ++i) { 5121 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 5122 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; 5123 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 5124 } 5125 /* top */ 5126 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 5127 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; 5128 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 5129 } 5130 5131 /* Top Slice */ 5132 /* bottom */ 5133 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 5134 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5135 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 5136 /* middle */ 5137 for (i = 0; i < k-1; ++i) { 5138 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 5139 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 5140 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 5141 } 5142 /* top */ 5143 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 5144 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 5145 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 5146 5147 foffset = offset; 5148 } 5149 break; 5150 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d); 5151 } 5152 } 5153 if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 5154 /* Check permutation */ 5155 { 5156 PetscInt *check; 5157 5158 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 5159 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]);} 5160 for (i = 0; i < size; ++i) check[perm[i]] = i; 5161 for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 5162 ierr = PetscFree(check);CHKERRQ(ierr); 5163 } 5164 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 5165 } 5166 PetscFunctionReturn(0); 5167 } 5168 5169 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5170 { 5171 PetscDS prob; 5172 PetscInt depth, Nf, h; 5173 DMLabel label; 5174 PetscErrorCode ierr; 5175 5176 PetscFunctionBeginHot; 5177 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 5178 Nf = prob->Nf; 5179 label = dm->depthLabel; 5180 *dspace = NULL; 5181 if (field < Nf) { 5182 PetscObject disc = prob->disc[field]; 5183 5184 if (disc->classid == PETSCFE_CLASSID) { 5185 PetscDualSpace dsp; 5186 5187 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 5188 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 5189 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 5190 h = depth - 1 - h; 5191 if (h) { 5192 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 5193 } else { 5194 *dspace = dsp; 5195 } 5196 } 5197 } 5198 PetscFunctionReturn(0); 5199 } 5200 5201 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5202 { 5203 PetscScalar *array, *vArray; 5204 const PetscInt *cone, *coneO; 5205 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 5206 PetscErrorCode ierr; 5207 5208 PetscFunctionBeginHot; 5209 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5210 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5211 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5212 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5213 if (!values || !*values) { 5214 if ((point >= pStart) && (point < pEnd)) { 5215 PetscInt dof; 5216 5217 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5218 size += dof; 5219 } 5220 for (p = 0; p < numPoints; ++p) { 5221 const PetscInt cp = cone[p]; 5222 PetscInt dof; 5223 5224 if ((cp < pStart) || (cp >= pEnd)) continue; 5225 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5226 size += dof; 5227 } 5228 if (!values) { 5229 if (csize) *csize = size; 5230 PetscFunctionReturn(0); 5231 } 5232 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 5233 } else { 5234 array = *values; 5235 } 5236 size = 0; 5237 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 5238 if ((point >= pStart) && (point < pEnd)) { 5239 PetscInt dof, off, d; 5240 PetscScalar *varr; 5241 5242 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5243 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5244 varr = &vArray[off]; 5245 for (d = 0; d < dof; ++d, ++offset) { 5246 array[offset] = varr[d]; 5247 } 5248 size += dof; 5249 } 5250 for (p = 0; p < numPoints; ++p) { 5251 const PetscInt cp = cone[p]; 5252 PetscInt o = coneO[p]; 5253 PetscInt dof, off, d; 5254 PetscScalar *varr; 5255 5256 if ((cp < pStart) || (cp >= pEnd)) continue; 5257 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5258 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 5259 varr = &vArray[off]; 5260 if (o >= 0) { 5261 for (d = 0; d < dof; ++d, ++offset) { 5262 array[offset] = varr[d]; 5263 } 5264 } else { 5265 for (d = dof-1; d >= 0; --d, ++offset) { 5266 array[offset] = varr[d]; 5267 } 5268 } 5269 size += dof; 5270 } 5271 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 5272 if (!*values) { 5273 if (csize) *csize = size; 5274 *values = array; 5275 } else { 5276 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5277 *csize = size; 5278 } 5279 PetscFunctionReturn(0); 5280 } 5281 5282 /* Compress out points not in the section */ 5283 PETSC_STATIC_INLINE PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 5284 { 5285 const PetscInt np = *numPoints; 5286 PetscInt pStart, pEnd, p, q; 5287 PetscErrorCode ierr; 5288 5289 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5290 for (p = 0, q = 0; p < np; ++p) { 5291 const PetscInt r = points[p*2]; 5292 if ((r >= pStart) && (r < pEnd)) { 5293 points[q*2] = r; 5294 points[q*2+1] = points[p*2+1]; 5295 ++q; 5296 } 5297 } 5298 *numPoints = q; 5299 return 0; 5300 } 5301 5302 static PetscErrorCode DMPlexTransitiveClosure_Hybrid_Internal(DM dm, PetscInt point, PetscInt np, PetscInt *numPoints, PetscInt **points) 5303 { 5304 const PetscInt *cone, *ornt; 5305 PetscInt *pts, *closure = NULL; 5306 PetscInt dim, coneSize, c, d, clSize, cl; 5307 PetscErrorCode ierr; 5308 5309 PetscFunctionBeginHot; 5310 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5311 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 5312 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5313 ierr = DMPlexGetConeOrientation(dm, point, &ornt);CHKERRQ(ierr); 5314 ierr = DMPlexGetTransitiveClosure(dm, cone[0], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 5315 ierr = DMGetWorkArray(dm, np*2, MPIU_INT, &pts);CHKERRQ(ierr); 5316 c = 0; 5317 pts[c*2+0] = point; 5318 pts[c*2+1] = 0; 5319 ++c; 5320 for (cl = 0; cl < clSize*2; cl += 2, ++c) {pts[c*2+0] = closure[cl]; pts[c*2+1] = closure[cl+1];} 5321 ierr = DMPlexGetTransitiveClosure(dm, cone[1], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 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 = DMPlexRestoreTransitiveClosure(dm, cone[0], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 5324 if (dim >= 2) { 5325 for (d = 2; d < coneSize; ++d, ++c) {pts[c*2+0] = cone[d]; pts[c*2+1] = ornt[d];} 5326 } 5327 if (dim >= 3) { 5328 for (d = 2; d < coneSize; ++d) { 5329 const PetscInt fpoint = cone[d]; 5330 const PetscInt *fcone; 5331 PetscInt fconeSize, fc, i; 5332 5333 ierr = DMPlexGetConeSize(dm, fpoint, &fconeSize);CHKERRQ(ierr); 5334 ierr = DMPlexGetCone(dm, fpoint, &fcone);CHKERRQ(ierr); 5335 for (fc = 0; fc < fconeSize; ++fc) { 5336 for (i = 0; i < c; ++i) if (pts[i*2] == fcone[fc]) break; 5337 if (i == c) {pts[c*2+0] = fcone[fc]; pts[c*2+1] = 0; ++c;} 5338 } 5339 } 5340 } 5341 if (c != np) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid closure for hybrid point %D, size %D != %D", point, c, np); 5342 *numPoints = np; 5343 *points = pts; 5344 PetscFunctionReturn(0); 5345 } 5346 5347 /* Compressed closure does not apply closure permutation */ 5348 PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5349 { 5350 const PetscInt *cla = NULL; 5351 PetscInt np, *pts = NULL; 5352 PetscErrorCode ierr; 5353 5354 PetscFunctionBeginHot; 5355 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 5356 if (*clPoints) { 5357 PetscInt dof, off; 5358 5359 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 5360 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 5361 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 5362 np = dof/2; 5363 pts = (PetscInt *) &cla[off]; 5364 } else { 5365 DMPolytopeType ct; 5366 5367 /* Do not make the label if it does not exist */ 5368 if (!dm->celltypeLabel) {ct = DM_POLYTOPE_POINT;} 5369 else {ierr = DMPlexGetCellType(dm, point, &ct);CHKERRQ(ierr);} 5370 switch (ct) { 5371 case DM_POLYTOPE_SEG_PRISM_TENSOR: 5372 ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 9, &np, &pts);CHKERRQ(ierr); 5373 break; 5374 case DM_POLYTOPE_TRI_PRISM_TENSOR: 5375 ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 21, &np, &pts);CHKERRQ(ierr); 5376 break; 5377 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 5378 ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 27, &np, &pts);CHKERRQ(ierr); 5379 break; 5380 default: 5381 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 5382 } 5383 ierr = CompressPoints_Private(section, &np, pts);CHKERRQ(ierr); 5384 } 5385 *numPoints = np; 5386 *points = pts; 5387 *clp = cla; 5388 PetscFunctionReturn(0); 5389 } 5390 5391 PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 5392 { 5393 PetscErrorCode ierr; 5394 5395 PetscFunctionBeginHot; 5396 if (!*clPoints) { 5397 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 5398 } else { 5399 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 5400 } 5401 *numPoints = 0; 5402 *points = NULL; 5403 *clSec = NULL; 5404 *clPoints = NULL; 5405 *clp = NULL; 5406 PetscFunctionReturn(0); 5407 } 5408 5409 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[]) 5410 { 5411 PetscInt offset = 0, p; 5412 const PetscInt **perms = NULL; 5413 const PetscScalar **flips = NULL; 5414 PetscErrorCode ierr; 5415 5416 PetscFunctionBeginHot; 5417 *size = 0; 5418 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5419 for (p = 0; p < numPoints; p++) { 5420 const PetscInt point = points[2*p]; 5421 const PetscInt *perm = perms ? perms[p] : NULL; 5422 const PetscScalar *flip = flips ? flips[p] : NULL; 5423 PetscInt dof, off, d; 5424 const PetscScalar *varr; 5425 5426 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5427 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5428 varr = &vArray[off]; 5429 if (clperm) { 5430 if (perm) { 5431 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 5432 } else { 5433 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 5434 } 5435 if (flip) { 5436 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 5437 } 5438 } else { 5439 if (perm) { 5440 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 5441 } else { 5442 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 5443 } 5444 if (flip) { 5445 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 5446 } 5447 } 5448 offset += dof; 5449 } 5450 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5451 *size = offset; 5452 PetscFunctionReturn(0); 5453 } 5454 5455 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[]) 5456 { 5457 PetscInt offset = 0, f; 5458 PetscErrorCode ierr; 5459 5460 PetscFunctionBeginHot; 5461 *size = 0; 5462 for (f = 0; f < numFields; ++f) { 5463 PetscInt p; 5464 const PetscInt **perms = NULL; 5465 const PetscScalar **flips = NULL; 5466 5467 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5468 for (p = 0; p < numPoints; p++) { 5469 const PetscInt point = points[2*p]; 5470 PetscInt fdof, foff, b; 5471 const PetscScalar *varr; 5472 const PetscInt *perm = perms ? perms[p] : NULL; 5473 const PetscScalar *flip = flips ? flips[p] : NULL; 5474 5475 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5476 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5477 varr = &vArray[foff]; 5478 if (clperm) { 5479 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 5480 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 5481 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 5482 } else { 5483 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 5484 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 5485 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 5486 } 5487 offset += fdof; 5488 } 5489 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5490 } 5491 *size = offset; 5492 PetscFunctionReturn(0); 5493 } 5494 5495 /*@C 5496 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 5497 5498 Not collective 5499 5500 Input Parameters: 5501 + dm - The DM 5502 . section - The section describing the layout in v, or NULL to use the default section 5503 . v - The local vector 5504 . point - The point in the DM 5505 . csize - The size of the input values array, or NULL 5506 - values - An array to use for the values, or NULL to have it allocated automatically 5507 5508 Output Parameters: 5509 + csize - The number of values in the closure 5510 - values - The array of values. If the user provided NULL, it is a borrowed array and should not be freed 5511 5512 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 5513 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 5514 $ assembly function, and a user may already have allocated storage for this operation. 5515 $ 5516 $ A typical use could be 5517 $ 5518 $ values = NULL; 5519 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5520 $ for (cl = 0; cl < clSize; ++cl) { 5521 $ <Compute on closure> 5522 $ } 5523 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5524 $ 5525 $ or 5526 $ 5527 $ PetscMalloc1(clMaxSize, &values); 5528 $ for (p = pStart; p < pEnd; ++p) { 5529 $ clSize = clMaxSize; 5530 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 5531 $ for (cl = 0; cl < clSize; ++cl) { 5532 $ <Compute on closure> 5533 $ } 5534 $ } 5535 $ PetscFree(values); 5536 5537 Fortran Notes: 5538 Since it returns an array, this routine is only available in Fortran 90, and you must 5539 include petsc.h90 in your code. 5540 5541 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5542 5543 Level: intermediate 5544 5545 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5546 @*/ 5547 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5548 { 5549 PetscSection clSection; 5550 IS clPoints; 5551 PetscInt *points = NULL; 5552 const PetscInt *clp, *perm; 5553 PetscInt depth, numFields, numPoints, asize; 5554 PetscErrorCode ierr; 5555 5556 PetscFunctionBeginHot; 5557 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5558 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5559 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5560 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5561 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5562 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5563 if (depth == 1 && numFields < 2) { 5564 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5565 PetscFunctionReturn(0); 5566 } 5567 /* Get points */ 5568 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5569 /* Get sizes */ 5570 asize = 0; 5571 for (PetscInt p = 0; p < numPoints*2; p += 2) { 5572 PetscInt dof; 5573 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5574 asize += dof; 5575 } 5576 if (values) { 5577 const PetscScalar *vArray; 5578 PetscInt size; 5579 5580 if (*values) { 5581 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); 5582 } else {ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, values);CHKERRQ(ierr);} 5583 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm);CHKERRQ(ierr); 5584 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5585 /* Get values */ 5586 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values);CHKERRQ(ierr);} 5587 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values);CHKERRQ(ierr);} 5588 if (PetscUnlikely(asize != size)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size); 5589 /* Cleanup array */ 5590 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5591 } 5592 if (csize) *csize = asize; 5593 /* Cleanup points */ 5594 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5595 PetscFunctionReturn(0); 5596 } 5597 5598 PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 5599 { 5600 DMLabel depthLabel; 5601 PetscSection clSection; 5602 IS clPoints; 5603 PetscScalar *array; 5604 const PetscScalar *vArray; 5605 PetscInt *points = NULL; 5606 const PetscInt *clp, *perm = NULL; 5607 PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 5608 PetscErrorCode ierr; 5609 5610 PetscFunctionBeginHot; 5611 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5612 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5613 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5614 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5615 ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr); 5616 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 5617 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5618 if (mdepth == 1 && numFields < 2) { 5619 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 5620 PetscFunctionReturn(0); 5621 } 5622 /* Get points */ 5623 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5624 for (clsize=0,p=0; p<Np; p++) { 5625 PetscInt dof; 5626 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 5627 clsize += dof; 5628 } 5629 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm);CHKERRQ(ierr); 5630 /* Filter points */ 5631 for (p = 0; p < numPoints*2; p += 2) { 5632 PetscInt dep; 5633 5634 ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr); 5635 if (dep != depth) continue; 5636 points[Np*2+0] = points[p]; 5637 points[Np*2+1] = points[p+1]; 5638 ++Np; 5639 } 5640 /* Get array */ 5641 if (!values || !*values) { 5642 PetscInt asize = 0, dof; 5643 5644 for (p = 0; p < Np*2; p += 2) { 5645 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5646 asize += dof; 5647 } 5648 if (!values) { 5649 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5650 if (csize) *csize = asize; 5651 PetscFunctionReturn(0); 5652 } 5653 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 5654 } else { 5655 array = *values; 5656 } 5657 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 5658 /* Get values */ 5659 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 5660 else {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);} 5661 /* Cleanup points */ 5662 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5663 /* Cleanup array */ 5664 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 5665 if (!*values) { 5666 if (csize) *csize = size; 5667 *values = array; 5668 } else { 5669 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 5670 *csize = size; 5671 } 5672 PetscFunctionReturn(0); 5673 } 5674 5675 /*@C 5676 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 5677 5678 Not collective 5679 5680 Input Parameters: 5681 + dm - The DM 5682 . section - The section describing the layout in v, or NULL to use the default section 5683 . v - The local vector 5684 . point - The point in the DM 5685 . csize - The number of values in the closure, or NULL 5686 - values - The array of values, which is a borrowed array and should not be freed 5687 5688 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 5689 5690 Fortran Notes: 5691 Since it returns an array, this routine is only available in Fortran 90, and you must 5692 include petsc.h90 in your code. 5693 5694 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 5695 5696 Level: intermediate 5697 5698 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 5699 @*/ 5700 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5701 { 5702 PetscInt size = 0; 5703 PetscErrorCode ierr; 5704 5705 PetscFunctionBegin; 5706 /* Should work without recalculating size */ 5707 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 5708 *values = NULL; 5709 PetscFunctionReturn(0); 5710 } 5711 5712 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 5713 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 5714 5715 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[]) 5716 { 5717 PetscInt cdof; /* The number of constraints on this point */ 5718 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5719 PetscScalar *a; 5720 PetscInt off, cind = 0, k; 5721 PetscErrorCode ierr; 5722 5723 PetscFunctionBegin; 5724 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5725 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5726 a = &array[off]; 5727 if (!cdof || setBC) { 5728 if (clperm) { 5729 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 5730 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 5731 } else { 5732 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 5733 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 5734 } 5735 } else { 5736 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5737 if (clperm) { 5738 if (perm) {for (k = 0; k < dof; ++k) { 5739 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5740 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5741 } 5742 } else { 5743 for (k = 0; k < dof; ++k) { 5744 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5745 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5746 } 5747 } 5748 } else { 5749 if (perm) { 5750 for (k = 0; k < dof; ++k) { 5751 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5752 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5753 } 5754 } else { 5755 for (k = 0; k < dof; ++k) { 5756 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5757 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5758 } 5759 } 5760 } 5761 } 5762 PetscFunctionReturn(0); 5763 } 5764 5765 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[]) 5766 { 5767 PetscInt cdof; /* The number of constraints on this point */ 5768 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5769 PetscScalar *a; 5770 PetscInt off, cind = 0, k; 5771 PetscErrorCode ierr; 5772 5773 PetscFunctionBegin; 5774 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5775 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 5776 a = &array[off]; 5777 if (cdof) { 5778 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5779 if (clperm) { 5780 if (perm) { 5781 for (k = 0; k < dof; ++k) { 5782 if ((cind < cdof) && (k == cdofs[cind])) { 5783 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 5784 cind++; 5785 } 5786 } 5787 } else { 5788 for (k = 0; k < dof; ++k) { 5789 if ((cind < cdof) && (k == cdofs[cind])) { 5790 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 5791 cind++; 5792 } 5793 } 5794 } 5795 } else { 5796 if (perm) { 5797 for (k = 0; k < dof; ++k) { 5798 if ((cind < cdof) && (k == cdofs[cind])) { 5799 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 5800 cind++; 5801 } 5802 } 5803 } else { 5804 for (k = 0; k < dof; ++k) { 5805 if ((cind < cdof) && (k == cdofs[cind])) { 5806 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 5807 cind++; 5808 } 5809 } 5810 } 5811 } 5812 } 5813 PetscFunctionReturn(0); 5814 } 5815 5816 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[]) 5817 { 5818 PetscScalar *a; 5819 PetscInt fdof, foff, fcdof, foffset = *offset; 5820 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5821 PetscInt cind = 0, b; 5822 PetscErrorCode ierr; 5823 5824 PetscFunctionBegin; 5825 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5826 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 5827 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5828 a = &array[foff]; 5829 if (!fcdof || setBC) { 5830 if (clperm) { 5831 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 5832 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 5833 } else { 5834 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 5835 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 5836 } 5837 } else { 5838 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5839 if (clperm) { 5840 if (perm) { 5841 for (b = 0; b < fdof; b++) { 5842 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5843 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 5844 } 5845 } else { 5846 for (b = 0; b < fdof; b++) { 5847 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5848 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 5849 } 5850 } 5851 } else { 5852 if (perm) { 5853 for (b = 0; b < fdof; b++) { 5854 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5855 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 5856 } 5857 } else { 5858 for (b = 0; b < fdof; b++) { 5859 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 5860 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 5861 } 5862 } 5863 } 5864 } 5865 *offset += fdof; 5866 PetscFunctionReturn(0); 5867 } 5868 5869 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[]) 5870 { 5871 PetscScalar *a; 5872 PetscInt fdof, foff, fcdof, foffset = *offset; 5873 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5874 PetscInt Nc, cind = 0, ncind = 0, b; 5875 PetscBool ncSet, fcSet; 5876 PetscErrorCode ierr; 5877 5878 PetscFunctionBegin; 5879 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 5880 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5881 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 5882 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 5883 a = &array[foff]; 5884 if (fcdof) { 5885 /* We just override fcdof and fcdofs with Ncc and comps */ 5886 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5887 if (clperm) { 5888 if (perm) { 5889 if (comps) { 5890 for (b = 0; b < fdof; b++) { 5891 ncSet = fcSet = PETSC_FALSE; 5892 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5893 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5894 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 5895 } 5896 } else { 5897 for (b = 0; b < fdof; b++) { 5898 if ((cind < fcdof) && (b == fcdofs[cind])) { 5899 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 5900 ++cind; 5901 } 5902 } 5903 } 5904 } else { 5905 if (comps) { 5906 for (b = 0; b < fdof; b++) { 5907 ncSet = fcSet = PETSC_FALSE; 5908 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5909 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5910 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 5911 } 5912 } else { 5913 for (b = 0; b < fdof; b++) { 5914 if ((cind < fcdof) && (b == fcdofs[cind])) { 5915 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 5916 ++cind; 5917 } 5918 } 5919 } 5920 } 5921 } else { 5922 if (perm) { 5923 if (comps) { 5924 for (b = 0; b < fdof; b++) { 5925 ncSet = fcSet = PETSC_FALSE; 5926 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5927 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5928 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 5929 } 5930 } else { 5931 for (b = 0; b < fdof; b++) { 5932 if ((cind < fcdof) && (b == fcdofs[cind])) { 5933 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 5934 ++cind; 5935 } 5936 } 5937 } 5938 } else { 5939 if (comps) { 5940 for (b = 0; b < fdof; b++) { 5941 ncSet = fcSet = PETSC_FALSE; 5942 if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5943 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5944 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 5945 } 5946 } else { 5947 for (b = 0; b < fdof; b++) { 5948 if ((cind < fcdof) && (b == fcdofs[cind])) { 5949 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 5950 ++cind; 5951 } 5952 } 5953 } 5954 } 5955 } 5956 } 5957 *offset += fdof; 5958 PetscFunctionReturn(0); 5959 } 5960 5961 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 5962 { 5963 PetscScalar *array; 5964 const PetscInt *cone, *coneO; 5965 PetscInt pStart, pEnd, p, numPoints, off, dof; 5966 PetscErrorCode ierr; 5967 5968 PetscFunctionBeginHot; 5969 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5970 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5971 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5972 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5973 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 5974 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 5975 const PetscInt cp = !p ? point : cone[p-1]; 5976 const PetscInt o = !p ? 0 : coneO[p-1]; 5977 5978 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 5979 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5980 /* ADD_VALUES */ 5981 { 5982 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5983 PetscScalar *a; 5984 PetscInt cdof, coff, cind = 0, k; 5985 5986 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 5987 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 5988 a = &array[coff]; 5989 if (!cdof) { 5990 if (o >= 0) { 5991 for (k = 0; k < dof; ++k) { 5992 a[k] += values[off+k]; 5993 } 5994 } else { 5995 for (k = 0; k < dof; ++k) { 5996 a[k] += values[off+dof-k-1]; 5997 } 5998 } 5999 } else { 6000 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 6001 if (o >= 0) { 6002 for (k = 0; k < dof; ++k) { 6003 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6004 a[k] += values[off+k]; 6005 } 6006 } else { 6007 for (k = 0; k < dof; ++k) { 6008 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 6009 a[k] += values[off+dof-k-1]; 6010 } 6011 } 6012 } 6013 } 6014 } 6015 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6016 PetscFunctionReturn(0); 6017 } 6018 6019 /*@C 6020 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 6021 6022 Not collective 6023 6024 Input Parameters: 6025 + dm - The DM 6026 . section - The section describing the layout in v, or NULL to use the default section 6027 . v - The local vector 6028 . point - The point in the DM 6029 . values - The array of values 6030 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 6031 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 6032 6033 Fortran Notes: 6034 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 6035 6036 Level: intermediate 6037 6038 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 6039 @*/ 6040 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6041 { 6042 PetscSection clSection; 6043 IS clPoints; 6044 PetscScalar *array; 6045 PetscInt *points = NULL; 6046 const PetscInt *clp, *clperm = NULL; 6047 PetscInt depth, numFields, numPoints, p, clsize; 6048 PetscErrorCode ierr; 6049 6050 PetscFunctionBeginHot; 6051 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6052 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6053 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6054 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6055 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6056 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6057 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 6058 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 6059 PetscFunctionReturn(0); 6060 } 6061 /* Get points */ 6062 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6063 for (clsize=0,p=0; p<numPoints; p++) { 6064 PetscInt dof; 6065 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 6066 clsize += dof; 6067 } 6068 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 6069 /* Get array */ 6070 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6071 /* Get values */ 6072 if (numFields > 0) { 6073 PetscInt offset = 0, f; 6074 for (f = 0; f < numFields; ++f) { 6075 const PetscInt **perms = NULL; 6076 const PetscScalar **flips = NULL; 6077 6078 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6079 switch (mode) { 6080 case INSERT_VALUES: 6081 for (p = 0; p < numPoints; p++) { 6082 const PetscInt point = points[2*p]; 6083 const PetscInt *perm = perms ? perms[p] : NULL; 6084 const PetscScalar *flip = flips ? flips[p] : NULL; 6085 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 6086 } break; 6087 case INSERT_ALL_VALUES: 6088 for (p = 0; p < numPoints; p++) { 6089 const PetscInt point = points[2*p]; 6090 const PetscInt *perm = perms ? perms[p] : NULL; 6091 const PetscScalar *flip = flips ? flips[p] : NULL; 6092 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 6093 } break; 6094 case INSERT_BC_VALUES: 6095 for (p = 0; p < numPoints; p++) { 6096 const PetscInt point = points[2*p]; 6097 const PetscInt *perm = perms ? perms[p] : NULL; 6098 const PetscScalar *flip = flips ? flips[p] : NULL; 6099 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 6100 } break; 6101 case ADD_VALUES: 6102 for (p = 0; p < numPoints; p++) { 6103 const PetscInt point = points[2*p]; 6104 const PetscInt *perm = perms ? perms[p] : NULL; 6105 const PetscScalar *flip = flips ? flips[p] : NULL; 6106 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 6107 } break; 6108 case ADD_ALL_VALUES: 6109 for (p = 0; p < numPoints; p++) { 6110 const PetscInt point = points[2*p]; 6111 const PetscInt *perm = perms ? perms[p] : NULL; 6112 const PetscScalar *flip = flips ? flips[p] : NULL; 6113 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 6114 } break; 6115 case ADD_BC_VALUES: 6116 for (p = 0; p < numPoints; p++) { 6117 const PetscInt point = points[2*p]; 6118 const PetscInt *perm = perms ? perms[p] : NULL; 6119 const PetscScalar *flip = flips ? flips[p] : NULL; 6120 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 6121 } break; 6122 default: 6123 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6124 } 6125 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6126 } 6127 } else { 6128 PetscInt dof, off; 6129 const PetscInt **perms = NULL; 6130 const PetscScalar **flips = NULL; 6131 6132 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6133 switch (mode) { 6134 case INSERT_VALUES: 6135 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6136 const PetscInt point = points[2*p]; 6137 const PetscInt *perm = perms ? perms[p] : NULL; 6138 const PetscScalar *flip = flips ? flips[p] : NULL; 6139 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6140 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 6141 } break; 6142 case INSERT_ALL_VALUES: 6143 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6144 const PetscInt point = points[2*p]; 6145 const PetscInt *perm = perms ? perms[p] : NULL; 6146 const PetscScalar *flip = flips ? flips[p] : NULL; 6147 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6148 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 6149 } break; 6150 case INSERT_BC_VALUES: 6151 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6152 const PetscInt point = points[2*p]; 6153 const PetscInt *perm = perms ? perms[p] : NULL; 6154 const PetscScalar *flip = flips ? flips[p] : NULL; 6155 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6156 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 6157 } break; 6158 case ADD_VALUES: 6159 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6160 const PetscInt point = points[2*p]; 6161 const PetscInt *perm = perms ? perms[p] : NULL; 6162 const PetscScalar *flip = flips ? flips[p] : NULL; 6163 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6164 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 6165 } break; 6166 case ADD_ALL_VALUES: 6167 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6168 const PetscInt point = points[2*p]; 6169 const PetscInt *perm = perms ? perms[p] : NULL; 6170 const PetscScalar *flip = flips ? flips[p] : NULL; 6171 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6172 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 6173 } break; 6174 case ADD_BC_VALUES: 6175 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 6176 const PetscInt point = points[2*p]; 6177 const PetscInt *perm = perms ? perms[p] : NULL; 6178 const PetscScalar *flip = flips ? flips[p] : NULL; 6179 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6180 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 6181 } break; 6182 default: 6183 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6184 } 6185 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6186 } 6187 /* Cleanup points */ 6188 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6189 /* Cleanup array */ 6190 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6191 PetscFunctionReturn(0); 6192 } 6193 6194 /* Check whether the given point is in the label. If not, update the offset to skip this point */ 6195 PETSC_STATIC_INLINE PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 6196 { 6197 PetscFunctionBegin; 6198 if (label) { 6199 PetscInt val, fdof; 6200 PetscErrorCode ierr; 6201 6202 /* There is a problem with this: 6203 Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that 6204 touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell. 6205 Thus I am only going to check val != -1, not val != labelId 6206 */ 6207 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 6208 if (val < 0) { 6209 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6210 *offset += fdof; 6211 PetscFunctionReturn(1); 6212 } 6213 } 6214 PetscFunctionReturn(0); 6215 } 6216 6217 /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 6218 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) 6219 { 6220 PetscSection clSection; 6221 IS clPoints; 6222 PetscScalar *array; 6223 PetscInt *points = NULL; 6224 const PetscInt *clp; 6225 PetscInt numFields, numPoints, p; 6226 PetscInt offset = 0, f; 6227 PetscErrorCode ierr; 6228 6229 PetscFunctionBeginHot; 6230 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6231 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 6232 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6233 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 6234 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6235 /* Get points */ 6236 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6237 /* Get array */ 6238 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 6239 /* Get values */ 6240 for (f = 0; f < numFields; ++f) { 6241 const PetscInt **perms = NULL; 6242 const PetscScalar **flips = NULL; 6243 6244 if (!fieldActive[f]) { 6245 for (p = 0; p < numPoints*2; p += 2) { 6246 PetscInt fdof; 6247 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6248 offset += fdof; 6249 } 6250 continue; 6251 } 6252 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6253 switch (mode) { 6254 case INSERT_VALUES: 6255 for (p = 0; p < numPoints; p++) { 6256 const PetscInt point = points[2*p]; 6257 const PetscInt *perm = perms ? perms[p] : NULL; 6258 const PetscScalar *flip = flips ? flips[p] : NULL; 6259 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6260 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array); 6261 } break; 6262 case INSERT_ALL_VALUES: 6263 for (p = 0; p < numPoints; p++) { 6264 const PetscInt point = points[2*p]; 6265 const PetscInt *perm = perms ? perms[p] : NULL; 6266 const PetscScalar *flip = flips ? flips[p] : NULL; 6267 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6268 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array); 6269 } break; 6270 case INSERT_BC_VALUES: 6271 for (p = 0; p < numPoints; p++) { 6272 const PetscInt point = points[2*p]; 6273 const PetscInt *perm = perms ? perms[p] : NULL; 6274 const PetscScalar *flip = flips ? flips[p] : NULL; 6275 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6276 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array); 6277 } break; 6278 case ADD_VALUES: 6279 for (p = 0; p < numPoints; p++) { 6280 const PetscInt point = points[2*p]; 6281 const PetscInt *perm = perms ? perms[p] : NULL; 6282 const PetscScalar *flip = flips ? flips[p] : NULL; 6283 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6284 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array); 6285 } break; 6286 case ADD_ALL_VALUES: 6287 for (p = 0; p < numPoints; p++) { 6288 const PetscInt point = points[2*p]; 6289 const PetscInt *perm = perms ? perms[p] : NULL; 6290 const PetscScalar *flip = flips ? flips[p] : NULL; 6291 ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 6292 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array); 6293 } break; 6294 default: 6295 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6296 } 6297 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 6298 } 6299 /* Cleanup points */ 6300 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6301 /* Cleanup array */ 6302 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 6303 PetscFunctionReturn(0); 6304 } 6305 6306 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 6307 { 6308 PetscMPIInt rank; 6309 PetscInt i, j; 6310 PetscErrorCode ierr; 6311 6312 PetscFunctionBegin; 6313 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr); 6314 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 6315 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 6316 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 6317 numCIndices = numCIndices ? numCIndices : numRIndices; 6318 if (!values) PetscFunctionReturn(0); 6319 for (i = 0; i < numRIndices; i++) { 6320 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 6321 for (j = 0; j < numCIndices; j++) { 6322 #if defined(PETSC_USE_COMPLEX) 6323 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 6324 #else 6325 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 6326 #endif 6327 } 6328 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 6329 } 6330 PetscFunctionReturn(0); 6331 } 6332 6333 /* 6334 DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 6335 6336 Input Parameters: 6337 + section - The section for this data layout 6338 . islocal - Is the section (and thus indices being requested) local or global? 6339 . point - The point contributing dofs with these indices 6340 . off - The global offset of this point 6341 . loff - The local offset of each field 6342 . setBC - The flag determining whether to include indices of bounsary values 6343 . perm - A permutation of the dofs on this point, or NULL 6344 - indperm - A permutation of the entire indices array, or NULL 6345 6346 Output Parameter: 6347 . indices - Indices for dofs on this point 6348 6349 Level: developer 6350 6351 Note: The indices could be local or global, depending on the value of 'off'. 6352 */ 6353 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 6354 { 6355 PetscInt dof; /* The number of unknowns on this point */ 6356 PetscInt cdof; /* The number of constraints on this point */ 6357 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6358 PetscInt cind = 0, k; 6359 PetscErrorCode ierr; 6360 6361 PetscFunctionBegin; 6362 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6363 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 6364 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 6365 if (!cdof || setBC) { 6366 for (k = 0; k < dof; ++k) { 6367 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6368 const PetscInt ind = indperm ? indperm[preind] : preind; 6369 6370 indices[ind] = off + k; 6371 } 6372 } else { 6373 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 6374 for (k = 0; k < dof; ++k) { 6375 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 6376 const PetscInt ind = indperm ? indperm[preind] : preind; 6377 6378 if ((cind < cdof) && (k == cdofs[cind])) { 6379 /* Insert check for returning constrained indices */ 6380 indices[ind] = -(off+k+1); 6381 ++cind; 6382 } else { 6383 indices[ind] = off + k - (islocal ? 0 : cind); 6384 } 6385 } 6386 } 6387 *loff += dof; 6388 PetscFunctionReturn(0); 6389 } 6390 6391 /* 6392 DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 6393 6394 Input Parameters: 6395 + section - a section (global or local) 6396 - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 6397 . point - point within section 6398 . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 6399 . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 6400 . setBC - identify constrained (boundary condition) points via involution. 6401 . perms - perms[f][permsoff][:] is a permutation of dofs within each field 6402 . permsoff - offset 6403 - indperm - index permutation 6404 6405 Output Parameter: 6406 . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 6407 . indices - array to hold indices (as defined by section) of each dof associated with point 6408 6409 Notes: 6410 If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 6411 If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 6412 in the local vector. 6413 6414 If section is global and setBC=false, the indices for constrained points are negative (and their value is not 6415 significant). It is invalid to call with a global section and setBC=true. 6416 6417 Developer Note: 6418 The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 6419 in the future, global sections may have fields set, in which case we could pass the global section and obtain the 6420 offset could be obtained from the section instead of passing it explicitly as we do now. 6421 6422 Example: 6423 Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 6424 When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 6425 Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 6426 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. 6427 6428 Level: developer 6429 */ 6430 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[]) 6431 { 6432 PetscInt numFields, foff, f; 6433 PetscErrorCode ierr; 6434 6435 PetscFunctionBegin; 6436 if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 6437 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6438 for (f = 0, foff = 0; f < numFields; ++f) { 6439 PetscInt fdof, cfdof; 6440 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6441 PetscInt cind = 0, b; 6442 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6443 6444 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6445 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6446 if (!cfdof || setBC) { 6447 for (b = 0; b < fdof; ++b) { 6448 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6449 const PetscInt ind = indperm ? indperm[preind] : preind; 6450 6451 indices[ind] = off+foff+b; 6452 } 6453 } else { 6454 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6455 for (b = 0; b < fdof; ++b) { 6456 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6457 const PetscInt ind = indperm ? indperm[preind] : preind; 6458 6459 if ((cind < cfdof) && (b == fcdofs[cind])) { 6460 indices[ind] = -(off+foff+b+1); 6461 ++cind; 6462 } else { 6463 indices[ind] = off + foff + b - (islocal ? 0 : cind); 6464 } 6465 } 6466 } 6467 foff += (setBC || islocal ? fdof : (fdof - cfdof)); 6468 foffs[f] += fdof; 6469 } 6470 PetscFunctionReturn(0); 6471 } 6472 6473 /* 6474 This version believes the globalSection offsets for each field, rather than just the point offset 6475 6476 . foffs - The offset into 'indices' for each field, since it is segregated by field 6477 6478 Notes: 6479 The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 6480 Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 6481 */ 6482 static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 6483 { 6484 PetscInt numFields, foff, f; 6485 PetscErrorCode ierr; 6486 6487 PetscFunctionBegin; 6488 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6489 for (f = 0; f < numFields; ++f) { 6490 PetscInt fdof, cfdof; 6491 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 6492 PetscInt cind = 0, b; 6493 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 6494 6495 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 6496 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 6497 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 6498 if (!cfdof) { 6499 for (b = 0; b < fdof; ++b) { 6500 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6501 const PetscInt ind = indperm ? indperm[preind] : preind; 6502 6503 indices[ind] = foff+b; 6504 } 6505 } else { 6506 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 6507 for (b = 0; b < fdof; ++b) { 6508 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 6509 const PetscInt ind = indperm ? indperm[preind] : preind; 6510 6511 if ((cind < cfdof) && (b == fcdofs[cind])) { 6512 indices[ind] = -(foff+b+1); 6513 ++cind; 6514 } else { 6515 indices[ind] = foff+b-cind; 6516 } 6517 } 6518 } 6519 foffs[f] += fdof; 6520 } 6521 PetscFunctionReturn(0); 6522 } 6523 6524 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) 6525 { 6526 Mat cMat; 6527 PetscSection aSec, cSec; 6528 IS aIS; 6529 PetscInt aStart = -1, aEnd = -1; 6530 const PetscInt *anchors; 6531 PetscInt numFields, f, p, q, newP = 0; 6532 PetscInt newNumPoints = 0, newNumIndices = 0; 6533 PetscInt *newPoints, *indices, *newIndices; 6534 PetscInt maxAnchor, maxDof; 6535 PetscInt newOffsets[32]; 6536 PetscInt *pointMatOffsets[32]; 6537 PetscInt *newPointOffsets[32]; 6538 PetscScalar *pointMat[32]; 6539 PetscScalar *newValues=NULL,*tmpValues; 6540 PetscBool anyConstrained = PETSC_FALSE; 6541 PetscErrorCode ierr; 6542 6543 PetscFunctionBegin; 6544 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6545 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6546 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6547 6548 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6549 /* if there are point-to-point constraints */ 6550 if (aSec) { 6551 ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr); 6552 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6553 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 6554 /* figure out how many points are going to be in the new element matrix 6555 * (we allow double counting, because it's all just going to be summed 6556 * into the global matrix anyway) */ 6557 for (p = 0; p < 2*numPoints; p+=2) { 6558 PetscInt b = points[p]; 6559 PetscInt bDof = 0, bSecDof; 6560 6561 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6562 if (!bSecDof) { 6563 continue; 6564 } 6565 if (b >= aStart && b < aEnd) { 6566 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 6567 } 6568 if (bDof) { 6569 /* this point is constrained */ 6570 /* it is going to be replaced by its anchors */ 6571 PetscInt bOff, q; 6572 6573 anyConstrained = PETSC_TRUE; 6574 newNumPoints += bDof; 6575 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 6576 for (q = 0; q < bDof; q++) { 6577 PetscInt a = anchors[bOff + q]; 6578 PetscInt aDof; 6579 6580 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6581 newNumIndices += aDof; 6582 for (f = 0; f < numFields; ++f) { 6583 PetscInt fDof; 6584 6585 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 6586 newOffsets[f+1] += fDof; 6587 } 6588 } 6589 } 6590 else { 6591 /* this point is not constrained */ 6592 newNumPoints++; 6593 newNumIndices += bSecDof; 6594 for (f = 0; f < numFields; ++f) { 6595 PetscInt fDof; 6596 6597 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6598 newOffsets[f+1] += fDof; 6599 } 6600 } 6601 } 6602 } 6603 if (!anyConstrained) { 6604 if (outNumPoints) *outNumPoints = 0; 6605 if (outNumIndices) *outNumIndices = 0; 6606 if (outPoints) *outPoints = NULL; 6607 if (outValues) *outValues = NULL; 6608 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6609 PetscFunctionReturn(0); 6610 } 6611 6612 if (outNumPoints) *outNumPoints = newNumPoints; 6613 if (outNumIndices) *outNumIndices = newNumIndices; 6614 6615 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 6616 6617 if (!outPoints && !outValues) { 6618 if (offsets) { 6619 for (f = 0; f <= numFields; f++) { 6620 offsets[f] = newOffsets[f]; 6621 } 6622 } 6623 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 6624 PetscFunctionReturn(0); 6625 } 6626 6627 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 6628 6629 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 6630 6631 /* workspaces */ 6632 if (numFields) { 6633 for (f = 0; f < numFields; f++) { 6634 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 6635 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6636 } 6637 } 6638 else { 6639 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 6640 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6641 } 6642 6643 /* get workspaces for the point-to-point matrices */ 6644 if (numFields) { 6645 PetscInt totalOffset, totalMatOffset; 6646 6647 for (p = 0; p < numPoints; p++) { 6648 PetscInt b = points[2*p]; 6649 PetscInt bDof = 0, bSecDof; 6650 6651 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6652 if (!bSecDof) { 6653 for (f = 0; f < numFields; f++) { 6654 newPointOffsets[f][p + 1] = 0; 6655 pointMatOffsets[f][p + 1] = 0; 6656 } 6657 continue; 6658 } 6659 if (b >= aStart && b < aEnd) { 6660 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6661 } 6662 if (bDof) { 6663 for (f = 0; f < numFields; f++) { 6664 PetscInt fDof, q, bOff, allFDof = 0; 6665 6666 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6667 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6668 for (q = 0; q < bDof; q++) { 6669 PetscInt a = anchors[bOff + q]; 6670 PetscInt aFDof; 6671 6672 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 6673 allFDof += aFDof; 6674 } 6675 newPointOffsets[f][p+1] = allFDof; 6676 pointMatOffsets[f][p+1] = fDof * allFDof; 6677 } 6678 } 6679 else { 6680 for (f = 0; f < numFields; f++) { 6681 PetscInt fDof; 6682 6683 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 6684 newPointOffsets[f][p+1] = fDof; 6685 pointMatOffsets[f][p+1] = 0; 6686 } 6687 } 6688 } 6689 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 6690 newPointOffsets[f][0] = totalOffset; 6691 pointMatOffsets[f][0] = totalMatOffset; 6692 for (p = 0; p < numPoints; p++) { 6693 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 6694 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 6695 } 6696 totalOffset = newPointOffsets[f][numPoints]; 6697 totalMatOffset = pointMatOffsets[f][numPoints]; 6698 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 6699 } 6700 } 6701 else { 6702 for (p = 0; p < numPoints; p++) { 6703 PetscInt b = points[2*p]; 6704 PetscInt bDof = 0, bSecDof; 6705 6706 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 6707 if (!bSecDof) { 6708 newPointOffsets[0][p + 1] = 0; 6709 pointMatOffsets[0][p + 1] = 0; 6710 continue; 6711 } 6712 if (b >= aStart && b < aEnd) { 6713 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6714 } 6715 if (bDof) { 6716 PetscInt bOff, q, allDof = 0; 6717 6718 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6719 for (q = 0; q < bDof; q++) { 6720 PetscInt a = anchors[bOff + q], aDof; 6721 6722 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 6723 allDof += aDof; 6724 } 6725 newPointOffsets[0][p+1] = allDof; 6726 pointMatOffsets[0][p+1] = bSecDof * allDof; 6727 } 6728 else { 6729 newPointOffsets[0][p+1] = bSecDof; 6730 pointMatOffsets[0][p+1] = 0; 6731 } 6732 } 6733 newPointOffsets[0][0] = 0; 6734 pointMatOffsets[0][0] = 0; 6735 for (p = 0; p < numPoints; p++) { 6736 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 6737 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 6738 } 6739 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 6740 } 6741 6742 /* output arrays */ 6743 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6744 6745 /* get the point-to-point matrices; construct newPoints */ 6746 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 6747 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 6748 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 6749 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 6750 if (numFields) { 6751 for (p = 0, newP = 0; p < numPoints; p++) { 6752 PetscInt b = points[2*p]; 6753 PetscInt o = points[2*p+1]; 6754 PetscInt bDof = 0, bSecDof; 6755 6756 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6757 if (!bSecDof) { 6758 continue; 6759 } 6760 if (b >= aStart && b < aEnd) { 6761 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6762 } 6763 if (bDof) { 6764 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 6765 6766 fStart[0] = 0; 6767 fEnd[0] = 0; 6768 for (f = 0; f < numFields; f++) { 6769 PetscInt fDof; 6770 6771 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 6772 fStart[f+1] = fStart[f] + fDof; 6773 fEnd[f+1] = fStart[f+1]; 6774 } 6775 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6776 ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 6777 6778 fAnchorStart[0] = 0; 6779 fAnchorEnd[0] = 0; 6780 for (f = 0; f < numFields; f++) { 6781 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 6782 6783 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 6784 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 6785 } 6786 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 6787 for (q = 0; q < bDof; q++) { 6788 PetscInt a = anchors[bOff + q], aOff; 6789 6790 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6791 newPoints[2*(newP + q)] = a; 6792 newPoints[2*(newP + q) + 1] = 0; 6793 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 6794 ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 6795 } 6796 newP += bDof; 6797 6798 if (outValues) { 6799 /* get the point-to-point submatrix */ 6800 for (f = 0; f < numFields; f++) { 6801 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 6802 } 6803 } 6804 } 6805 else { 6806 newPoints[2 * newP] = b; 6807 newPoints[2 * newP + 1] = o; 6808 newP++; 6809 } 6810 } 6811 } else { 6812 for (p = 0; p < numPoints; p++) { 6813 PetscInt b = points[2*p]; 6814 PetscInt o = points[2*p+1]; 6815 PetscInt bDof = 0, bSecDof; 6816 6817 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 6818 if (!bSecDof) { 6819 continue; 6820 } 6821 if (b >= aStart && b < aEnd) { 6822 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 6823 } 6824 if (bDof) { 6825 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 6826 6827 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 6828 ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 6829 6830 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 6831 for (q = 0; q < bDof; q++) { 6832 PetscInt a = anchors[bOff + q], aOff; 6833 6834 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6835 6836 newPoints[2*(newP + q)] = a; 6837 newPoints[2*(newP + q) + 1] = 0; 6838 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 6839 ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 6840 } 6841 newP += bDof; 6842 6843 /* get the point-to-point submatrix */ 6844 if (outValues) { 6845 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 6846 } 6847 } 6848 else { 6849 newPoints[2 * newP] = b; 6850 newPoints[2 * newP + 1] = o; 6851 newP++; 6852 } 6853 } 6854 } 6855 6856 if (outValues) { 6857 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 6858 ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr); 6859 /* multiply constraints on the right */ 6860 if (numFields) { 6861 for (f = 0; f < numFields; f++) { 6862 PetscInt oldOff = offsets[f]; 6863 6864 for (p = 0; p < numPoints; p++) { 6865 PetscInt cStart = newPointOffsets[f][p]; 6866 PetscInt b = points[2 * p]; 6867 PetscInt c, r, k; 6868 PetscInt dof; 6869 6870 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 6871 if (!dof) { 6872 continue; 6873 } 6874 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 6875 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 6876 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 6877 6878 for (r = 0; r < numIndices; r++) { 6879 for (c = 0; c < nCols; c++) { 6880 for (k = 0; k < dof; k++) { 6881 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 6882 } 6883 } 6884 } 6885 } 6886 else { 6887 /* copy this column as is */ 6888 for (r = 0; r < numIndices; r++) { 6889 for (c = 0; c < dof; c++) { 6890 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 6891 } 6892 } 6893 } 6894 oldOff += dof; 6895 } 6896 } 6897 } 6898 else { 6899 PetscInt oldOff = 0; 6900 for (p = 0; p < numPoints; p++) { 6901 PetscInt cStart = newPointOffsets[0][p]; 6902 PetscInt b = points[2 * p]; 6903 PetscInt c, r, k; 6904 PetscInt dof; 6905 6906 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 6907 if (!dof) { 6908 continue; 6909 } 6910 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 6911 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 6912 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 6913 6914 for (r = 0; r < numIndices; r++) { 6915 for (c = 0; c < nCols; c++) { 6916 for (k = 0; k < dof; k++) { 6917 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 6918 } 6919 } 6920 } 6921 } 6922 else { 6923 /* copy this column as is */ 6924 for (r = 0; r < numIndices; r++) { 6925 for (c = 0; c < dof; c++) { 6926 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 6927 } 6928 } 6929 } 6930 oldOff += dof; 6931 } 6932 } 6933 6934 if (multiplyLeft) { 6935 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 6936 ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr); 6937 /* multiply constraints transpose on the left */ 6938 if (numFields) { 6939 for (f = 0; f < numFields; f++) { 6940 PetscInt oldOff = offsets[f]; 6941 6942 for (p = 0; p < numPoints; p++) { 6943 PetscInt rStart = newPointOffsets[f][p]; 6944 PetscInt b = points[2 * p]; 6945 PetscInt c, r, k; 6946 PetscInt dof; 6947 6948 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 6949 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 6950 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 6951 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 6952 6953 for (r = 0; r < nRows; r++) { 6954 for (c = 0; c < newNumIndices; c++) { 6955 for (k = 0; k < dof; k++) { 6956 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 6957 } 6958 } 6959 } 6960 } 6961 else { 6962 /* copy this row as is */ 6963 for (r = 0; r < dof; r++) { 6964 for (c = 0; c < newNumIndices; c++) { 6965 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 6966 } 6967 } 6968 } 6969 oldOff += dof; 6970 } 6971 } 6972 } 6973 else { 6974 PetscInt oldOff = 0; 6975 6976 for (p = 0; p < numPoints; p++) { 6977 PetscInt rStart = newPointOffsets[0][p]; 6978 PetscInt b = points[2 * p]; 6979 PetscInt c, r, k; 6980 PetscInt dof; 6981 6982 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 6983 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 6984 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 6985 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 6986 6987 for (r = 0; r < nRows; r++) { 6988 for (c = 0; c < newNumIndices; c++) { 6989 for (k = 0; k < dof; k++) { 6990 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 6991 } 6992 } 6993 } 6994 } 6995 else { 6996 /* copy this row as is */ 6997 for (r = 0; r < dof; r++) { 6998 for (c = 0; c < newNumIndices; c++) { 6999 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7000 } 7001 } 7002 } 7003 oldOff += dof; 7004 } 7005 } 7006 7007 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 7008 } 7009 else { 7010 newValues = tmpValues; 7011 } 7012 } 7013 7014 /* clean up */ 7015 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 7016 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 7017 7018 if (numFields) { 7019 for (f = 0; f < numFields; f++) { 7020 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 7021 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 7022 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 7023 } 7024 } 7025 else { 7026 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 7027 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 7028 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 7029 } 7030 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7031 7032 /* output */ 7033 if (outPoints) { 7034 *outPoints = newPoints; 7035 } 7036 else { 7037 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 7038 } 7039 if (outValues) { 7040 *outValues = newValues; 7041 } 7042 for (f = 0; f <= numFields; f++) { 7043 offsets[f] = newOffsets[f]; 7044 } 7045 PetscFunctionReturn(0); 7046 } 7047 7048 /*@C 7049 DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 7050 7051 Not collective 7052 7053 Input Parameters: 7054 + dm - The DM 7055 . section - The PetscSection describing the points (a local section) 7056 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7057 . point - The point defining the closure 7058 - useClPerm - Use the closure point permutation if available 7059 7060 Output Parameters: 7061 + numIndices - The number of dof indices in the closure of point with the input sections 7062 . indices - The dof indices 7063 . outOffsets - Array to write the field offsets into, or NULL 7064 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7065 7066 Notes: 7067 Must call DMPlexRestoreClosureIndices() to free allocated memory 7068 7069 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7070 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7071 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7072 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7073 indices (with the above semantics) are implied. 7074 7075 Level: advanced 7076 7077 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7078 @*/ 7079 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7080 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7081 { 7082 /* Closure ordering */ 7083 PetscSection clSection; 7084 IS clPoints; 7085 const PetscInt *clp; 7086 PetscInt *points; 7087 const PetscInt *clperm = NULL; 7088 /* Dof permutation and sign flips */ 7089 const PetscInt **perms[32] = {NULL}; 7090 const PetscScalar **flips[32] = {NULL}; 7091 PetscScalar *valCopy = NULL; 7092 /* Hanging node constraints */ 7093 PetscInt *pointsC = NULL; 7094 PetscScalar *valuesC = NULL; 7095 PetscInt NclC, NiC; 7096 7097 PetscInt *idx; 7098 PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 7099 PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 7100 PetscErrorCode ierr; 7101 7102 PetscFunctionBeginHot; 7103 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7104 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7105 PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7106 if (numIndices) PetscValidPointer(numIndices, 6); 7107 if (indices) PetscValidPointer(indices, 7); 7108 if (outOffsets) PetscValidPointer(outOffsets, 8); 7109 if (values) PetscValidPointer(values, 9); 7110 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 7111 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 7112 ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 7113 /* 1) Get points in closure */ 7114 ierr = DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7115 if (useClPerm) { 7116 PetscInt depth, clsize; 7117 ierr = DMPlexGetPointDepth(dm, point, &depth);CHKERRQ(ierr); 7118 for (clsize=0,p=0; p<Ncl; p++) { 7119 PetscInt dof; 7120 ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr); 7121 clsize += dof; 7122 } 7123 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr); 7124 } 7125 /* 2) Get number of indices on these points and field offsets from section */ 7126 for (p = 0; p < Ncl*2; p += 2) { 7127 PetscInt dof, fdof; 7128 7129 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7130 for (f = 0; f < Nf; ++f) { 7131 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7132 offsets[f+1] += fdof; 7133 } 7134 Ni += dof; 7135 } 7136 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 7137 if (Nf && offsets[Nf] != Ni) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni); 7138 /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 7139 for (f = 0; f < PetscMax(1, Nf); ++f) { 7140 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7141 else {ierr = PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7142 /* may need to apply sign changes to the element matrix */ 7143 if (values && flips[f]) { 7144 PetscInt foffset = offsets[f]; 7145 7146 for (p = 0; p < Ncl; ++p) { 7147 PetscInt pnt = points[2*p], fdof; 7148 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 7149 7150 if (!Nf) {ierr = PetscSectionGetDof(section, pnt, &fdof);CHKERRQ(ierr);} 7151 else {ierr = PetscSectionGetFieldDof(section, pnt, f, &fdof);CHKERRQ(ierr);} 7152 if (flip) { 7153 PetscInt i, j, k; 7154 7155 if (!valCopy) { 7156 ierr = DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr); 7157 for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 7158 *values = valCopy; 7159 } 7160 for (i = 0; i < fdof; ++i) { 7161 PetscScalar fval = flip[i]; 7162 7163 for (k = 0; k < Ni; ++k) { 7164 valCopy[Ni * (foffset + i) + k] *= fval; 7165 valCopy[Ni * k + (foffset + i)] *= fval; 7166 } 7167 } 7168 } 7169 foffset += fdof; 7170 } 7171 } 7172 } 7173 /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 7174 ierr = DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 7175 if (NclC) { 7176 if (valCopy) {ierr = DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);} 7177 for (f = 0; f < PetscMax(1, Nf); ++f) { 7178 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7179 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7180 } 7181 for (f = 0; f < PetscMax(1, Nf); ++f) { 7182 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7183 else {ierr = PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);} 7184 } 7185 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7186 Ncl = NclC; 7187 Ni = NiC; 7188 points = pointsC; 7189 if (values) *values = valuesC; 7190 } 7191 /* 5) Calculate indices */ 7192 ierr = DMGetWorkArray(dm, Ni, MPIU_INT, &idx);CHKERRQ(ierr); 7193 if (Nf) { 7194 PetscInt idxOff; 7195 PetscBool useFieldOffsets; 7196 7197 if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];} 7198 ierr = PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets);CHKERRQ(ierr); 7199 if (useFieldOffsets) { 7200 for (p = 0; p < Ncl; ++p) { 7201 const PetscInt pnt = points[p*2]; 7202 7203 ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx);CHKERRQ(ierr); 7204 } 7205 } else { 7206 for (p = 0; p < Ncl; ++p) { 7207 const PetscInt pnt = points[p*2]; 7208 7209 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7210 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7211 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 7212 * global section. */ 7213 ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx);CHKERRQ(ierr); 7214 } 7215 } 7216 } else { 7217 PetscInt off = 0, idxOff; 7218 7219 for (p = 0; p < Ncl; ++p) { 7220 const PetscInt pnt = points[p*2]; 7221 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 7222 7223 ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr); 7224 /* Note that we pass a local section even though we're using global offsets. This is because global sections do 7225 * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 7226 ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx);CHKERRQ(ierr); 7227 } 7228 } 7229 /* 6) Cleanup */ 7230 for (f = 0; f < PetscMax(1, Nf); ++f) { 7231 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7232 else {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);} 7233 } 7234 if (NclC) { 7235 ierr = DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC);CHKERRQ(ierr); 7236 } else { 7237 ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr); 7238 } 7239 7240 if (numIndices) *numIndices = Ni; 7241 if (indices) *indices = idx; 7242 PetscFunctionReturn(0); 7243 } 7244 7245 /*@C 7246 DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 7247 7248 Not collective 7249 7250 Input Parameters: 7251 + dm - The DM 7252 . section - The PetscSection describing the points (a local section) 7253 . idxSection - The PetscSection from which to obtain indices (may be local or global) 7254 . point - The point defining the closure 7255 - useClPerm - Use the closure point permutation if available 7256 7257 Output Parameters: 7258 + numIndices - The number of dof indices in the closure of point with the input sections 7259 . indices - The dof indices 7260 . outOffsets - Array to write the field offsets into, or NULL 7261 - values - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL 7262 7263 Notes: 7264 If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values). 7265 7266 If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 7267 of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 7268 of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 7269 indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 7270 indices (with the above semantics) are implied. 7271 7272 Level: advanced 7273 7274 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 7275 @*/ 7276 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, 7277 PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7278 { 7279 PetscErrorCode ierr; 7280 7281 PetscFunctionBegin; 7282 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7283 PetscValidPointer(indices, 7); 7284 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 7285 PetscFunctionReturn(0); 7286 } 7287 7288 /*@C 7289 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 7290 7291 Not collective 7292 7293 Input Parameters: 7294 + dm - The DM 7295 . section - The section describing the layout in v, or NULL to use the default section 7296 . globalSection - The section describing the layout in v, or NULL to use the default global section 7297 . A - The matrix 7298 . point - The point in the DM 7299 . values - The array of values 7300 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7301 7302 Fortran Notes: 7303 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 7304 7305 Level: intermediate 7306 7307 .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7308 @*/ 7309 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7310 { 7311 DM_Plex *mesh = (DM_Plex*) dm->data; 7312 PetscInt *indices; 7313 PetscInt numIndices; 7314 const PetscScalar *valuesOrig = values; 7315 PetscErrorCode ierr; 7316 7317 PetscFunctionBegin; 7318 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7319 if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 7320 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7321 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 7322 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 7323 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 7324 7325 ierr = DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7326 7327 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 7328 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 7329 if (ierr) { 7330 PetscMPIInt rank; 7331 PetscErrorCode ierr2; 7332 7333 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7334 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7335 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 7336 ierr2 = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7337 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7338 CHKERRQ(ierr); 7339 } 7340 if (mesh->printFEM > 1) { 7341 PetscInt i; 7342 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 7343 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 7344 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7345 } 7346 7347 ierr = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7348 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7349 PetscFunctionReturn(0); 7350 } 7351 7352 /*@C 7353 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section 7354 7355 Not collective 7356 7357 Input Parameters: 7358 + dmRow - The DM for the row fields 7359 . sectionRow - The section describing the layout, or NULL to use the default section in dmRow 7360 . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow 7361 . dmCol - The DM for the column fields 7362 . sectionCol - The section describing the layout, or NULL to use the default section in dmCol 7363 . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol 7364 . A - The matrix 7365 . point - The point in the DMs 7366 . values - The array of values 7367 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7368 7369 Level: intermediate 7370 7371 .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure() 7372 @*/ 7373 PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7374 { 7375 DM_Plex *mesh = (DM_Plex*) dmRow->data; 7376 PetscInt *indicesRow, *indicesCol; 7377 PetscInt numIndicesRow, numIndicesCol; 7378 const PetscScalar *valuesOrig = values; 7379 PetscErrorCode ierr; 7380 7381 PetscFunctionBegin; 7382 PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 7383 if (!sectionRow) {ierr = DMGetLocalSection(dmRow, §ionRow);CHKERRQ(ierr);} 7384 PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 7385 if (!globalSectionRow) {ierr = DMGetGlobalSection(dmRow, &globalSectionRow);CHKERRQ(ierr);} 7386 PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 7387 PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4); 7388 if (!sectionCol) {ierr = DMGetLocalSection(dmCol, §ionCol);CHKERRQ(ierr);} 7389 PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5); 7390 if (!globalSectionCol) {ierr = DMGetGlobalSection(dmCol, &globalSectionCol);CHKERRQ(ierr);} 7391 PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6); 7392 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7393 7394 ierr = DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7395 ierr = DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7396 7397 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr);} 7398 ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 7399 if (ierr) { 7400 PetscMPIInt rank; 7401 PetscErrorCode ierr2; 7402 7403 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7404 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7405 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr2); 7406 ierr2 = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7407 ierr2 = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2); 7408 if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);} 7409 CHKERRQ(ierr); 7410 } 7411 7412 ierr = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7413 ierr = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr); 7414 if (values != valuesOrig) {ierr = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);} 7415 PetscFunctionReturn(0); 7416 } 7417 7418 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 7419 { 7420 DM_Plex *mesh = (DM_Plex*) dmf->data; 7421 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7422 PetscInt *cpoints = NULL; 7423 PetscInt *findices, *cindices; 7424 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7425 PetscInt foffsets[32], coffsets[32]; 7426 DMPolytopeType ct; 7427 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7428 PetscErrorCode ierr; 7429 7430 PetscFunctionBegin; 7431 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7432 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7433 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7434 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7435 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7436 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7437 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7438 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7439 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7440 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7441 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7442 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7443 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7444 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7445 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7446 /* Column indices */ 7447 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7448 maxFPoints = numCPoints; 7449 /* Compress out points not in the section */ 7450 /* TODO: Squeeze out points with 0 dof as well */ 7451 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7452 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7453 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7454 cpoints[q*2] = cpoints[p]; 7455 cpoints[q*2+1] = cpoints[p+1]; 7456 ++q; 7457 } 7458 } 7459 numCPoints = q; 7460 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7461 PetscInt fdof; 7462 7463 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7464 if (!dof) continue; 7465 for (f = 0; f < numFields; ++f) { 7466 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7467 coffsets[f+1] += fdof; 7468 } 7469 numCIndices += dof; 7470 } 7471 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7472 /* Row indices */ 7473 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7474 { 7475 DMPlexCellRefiner cr; 7476 ierr = DMPlexCellRefinerCreate(dmc, &cr);CHKERRQ(ierr); 7477 ierr = DMPlexCellRefinerGetAffineTransforms(cr, ct, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 7478 ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 7479 } 7480 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7481 for (r = 0, q = 0; r < numSubcells; ++r) { 7482 /* TODO Map from coarse to fine cells */ 7483 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7484 /* Compress out points not in the section */ 7485 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7486 for (p = 0; p < numFPoints*2; p += 2) { 7487 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7488 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7489 if (!dof) continue; 7490 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7491 if (s < q) continue; 7492 ftotpoints[q*2] = fpoints[p]; 7493 ftotpoints[q*2+1] = fpoints[p+1]; 7494 ++q; 7495 } 7496 } 7497 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7498 } 7499 numFPoints = q; 7500 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7501 PetscInt fdof; 7502 7503 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7504 if (!dof) continue; 7505 for (f = 0; f < numFields; ++f) { 7506 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7507 foffsets[f+1] += fdof; 7508 } 7509 numFIndices += dof; 7510 } 7511 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7512 7513 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7514 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7515 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7516 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7517 if (numFields) { 7518 const PetscInt **permsF[32] = {NULL}; 7519 const PetscInt **permsC[32] = {NULL}; 7520 7521 for (f = 0; f < numFields; f++) { 7522 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7523 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7524 } 7525 for (p = 0; p < numFPoints; p++) { 7526 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7527 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7528 } 7529 for (p = 0; p < numCPoints; p++) { 7530 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7531 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7532 } 7533 for (f = 0; f < numFields; f++) { 7534 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7535 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7536 } 7537 } else { 7538 const PetscInt **permsF = NULL; 7539 const PetscInt **permsC = NULL; 7540 7541 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7542 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7543 for (p = 0, off = 0; p < numFPoints; p++) { 7544 const PetscInt *perm = permsF ? permsF[p] : NULL; 7545 7546 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7547 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7548 } 7549 for (p = 0, off = 0; p < numCPoints; p++) { 7550 const PetscInt *perm = permsC ? permsC[p] : NULL; 7551 7552 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7553 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7554 } 7555 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7556 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7557 } 7558 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 7559 /* TODO: flips */ 7560 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 7561 if (ierr) { 7562 PetscMPIInt rank; 7563 PetscErrorCode ierr2; 7564 7565 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2); 7566 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 7567 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 7568 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 7569 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 7570 CHKERRQ(ierr); 7571 } 7572 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7573 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7574 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 7575 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 7576 PetscFunctionReturn(0); 7577 } 7578 7579 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 7580 { 7581 PetscInt *fpoints = NULL, *ftotpoints = NULL; 7582 PetscInt *cpoints = NULL; 7583 PetscInt foffsets[32], coffsets[32]; 7584 const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 7585 DMPolytopeType ct; 7586 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 7587 PetscErrorCode ierr; 7588 7589 PetscFunctionBegin; 7590 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 7591 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 7592 if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 7593 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 7594 if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 7595 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 7596 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 7597 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 7598 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 7599 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 7600 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 7601 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7602 ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 7603 ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 7604 /* Column indices */ 7605 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7606 maxFPoints = numCPoints; 7607 /* Compress out points not in the section */ 7608 /* TODO: Squeeze out points with 0 dof as well */ 7609 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 7610 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 7611 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 7612 cpoints[q*2] = cpoints[p]; 7613 cpoints[q*2+1] = cpoints[p+1]; 7614 ++q; 7615 } 7616 } 7617 numCPoints = q; 7618 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 7619 PetscInt fdof; 7620 7621 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 7622 if (!dof) continue; 7623 for (f = 0; f < numFields; ++f) { 7624 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 7625 coffsets[f+1] += fdof; 7626 } 7627 numCIndices += dof; 7628 } 7629 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 7630 /* Row indices */ 7631 ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 7632 { 7633 DMPlexCellRefiner cr; 7634 ierr = DMPlexCellRefinerCreate(dmc, &cr);CHKERRQ(ierr); 7635 ierr = DMPlexCellRefinerGetAffineTransforms(cr, ct, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 7636 ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 7637 } 7638 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7639 for (r = 0, q = 0; r < numSubcells; ++r) { 7640 /* TODO Map from coarse to fine cells */ 7641 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7642 /* Compress out points not in the section */ 7643 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 7644 for (p = 0; p < numFPoints*2; p += 2) { 7645 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 7646 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 7647 if (!dof) continue; 7648 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 7649 if (s < q) continue; 7650 ftotpoints[q*2] = fpoints[p]; 7651 ftotpoints[q*2+1] = fpoints[p+1]; 7652 ++q; 7653 } 7654 } 7655 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 7656 } 7657 numFPoints = q; 7658 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 7659 PetscInt fdof; 7660 7661 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 7662 if (!dof) continue; 7663 for (f = 0; f < numFields; ++f) { 7664 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 7665 foffsets[f+1] += fdof; 7666 } 7667 numFIndices += dof; 7668 } 7669 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 7670 7671 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 7672 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 7673 if (numFields) { 7674 const PetscInt **permsF[32] = {NULL}; 7675 const PetscInt **permsC[32] = {NULL}; 7676 7677 for (f = 0; f < numFields; f++) { 7678 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7679 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7680 } 7681 for (p = 0; p < numFPoints; p++) { 7682 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7683 ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 7684 } 7685 for (p = 0; p < numCPoints; p++) { 7686 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7687 ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 7688 } 7689 for (f = 0; f < numFields; f++) { 7690 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 7691 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 7692 } 7693 } else { 7694 const PetscInt **permsF = NULL; 7695 const PetscInt **permsC = NULL; 7696 7697 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7698 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7699 for (p = 0, off = 0; p < numFPoints; p++) { 7700 const PetscInt *perm = permsF ? permsF[p] : NULL; 7701 7702 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 7703 ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 7704 } 7705 for (p = 0, off = 0; p < numCPoints; p++) { 7706 const PetscInt *perm = permsC ? permsC[p] : NULL; 7707 7708 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 7709 ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 7710 } 7711 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 7712 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 7713 } 7714 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 7715 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 7716 PetscFunctionReturn(0); 7717 } 7718 7719 /*@C 7720 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 7721 7722 Input Parameter: 7723 . dm - The DMPlex object 7724 7725 Output Parameter: 7726 . cellHeight - The height of a cell 7727 7728 Level: developer 7729 7730 .seealso DMPlexSetVTKCellHeight() 7731 @*/ 7732 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 7733 { 7734 DM_Plex *mesh = (DM_Plex*) dm->data; 7735 7736 PetscFunctionBegin; 7737 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7738 PetscValidPointer(cellHeight, 2); 7739 *cellHeight = mesh->vtkCellHeight; 7740 PetscFunctionReturn(0); 7741 } 7742 7743 /*@C 7744 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 7745 7746 Input Parameters: 7747 + dm - The DMPlex object 7748 - cellHeight - The height of a cell 7749 7750 Level: developer 7751 7752 .seealso DMPlexGetVTKCellHeight() 7753 @*/ 7754 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 7755 { 7756 DM_Plex *mesh = (DM_Plex*) dm->data; 7757 7758 PetscFunctionBegin; 7759 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7760 mesh->vtkCellHeight = cellHeight; 7761 PetscFunctionReturn(0); 7762 } 7763 7764 /*@ 7765 DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 7766 7767 Input Parameter: 7768 . dm - The DMPlex object 7769 7770 Output Parameters: 7771 + gcStart - The first ghost cell, or NULL 7772 - gcEnd - The upper bound on ghost cells, or NULL 7773 7774 Level: advanced 7775 7776 .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum() 7777 @*/ 7778 PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 7779 { 7780 DMLabel ctLabel; 7781 PetscErrorCode ierr; 7782 7783 PetscFunctionBegin; 7784 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7785 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 7786 ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr); 7787 PetscFunctionReturn(0); 7788 } 7789 7790 /* We can easily have a form that takes an IS instead */ 7791 PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 7792 { 7793 PetscSection section, globalSection; 7794 PetscInt *numbers, p; 7795 PetscErrorCode ierr; 7796 7797 PetscFunctionBegin; 7798 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7799 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 7800 for (p = pStart; p < pEnd; ++p) { 7801 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 7802 } 7803 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 7804 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7805 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 7806 for (p = pStart; p < pEnd; ++p) { 7807 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 7808 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 7809 else numbers[p-pStart] += shift; 7810 } 7811 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 7812 if (globalSize) { 7813 PetscLayout layout; 7814 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 7815 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 7816 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 7817 } 7818 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7819 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 7820 PetscFunctionReturn(0); 7821 } 7822 7823 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 7824 { 7825 PetscInt cellHeight, cStart, cEnd; 7826 PetscErrorCode ierr; 7827 7828 PetscFunctionBegin; 7829 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 7830 if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 7831 else {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 7832 ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 7833 PetscFunctionReturn(0); 7834 } 7835 7836 /*@ 7837 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 7838 7839 Input Parameter: 7840 . dm - The DMPlex object 7841 7842 Output Parameter: 7843 . globalCellNumbers - Global cell numbers for all cells on this process 7844 7845 Level: developer 7846 7847 .seealso DMPlexGetVertexNumbering() 7848 @*/ 7849 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 7850 { 7851 DM_Plex *mesh = (DM_Plex*) dm->data; 7852 PetscErrorCode ierr; 7853 7854 PetscFunctionBegin; 7855 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7856 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 7857 *globalCellNumbers = mesh->globalCellNumbers; 7858 PetscFunctionReturn(0); 7859 } 7860 7861 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 7862 { 7863 PetscInt vStart, vEnd; 7864 PetscErrorCode ierr; 7865 7866 PetscFunctionBegin; 7867 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7868 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7869 ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 7870 PetscFunctionReturn(0); 7871 } 7872 7873 /*@ 7874 DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 7875 7876 Input Parameter: 7877 . dm - The DMPlex object 7878 7879 Output Parameter: 7880 . globalVertexNumbers - Global vertex numbers for all vertices on this process 7881 7882 Level: developer 7883 7884 .seealso DMPlexGetCellNumbering() 7885 @*/ 7886 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 7887 { 7888 DM_Plex *mesh = (DM_Plex*) dm->data; 7889 PetscErrorCode ierr; 7890 7891 PetscFunctionBegin; 7892 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7893 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 7894 *globalVertexNumbers = mesh->globalVertexNumbers; 7895 PetscFunctionReturn(0); 7896 } 7897 7898 /*@ 7899 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 7900 7901 Input Parameter: 7902 . dm - The DMPlex object 7903 7904 Output Parameter: 7905 . globalPointNumbers - Global numbers for all points on this process 7906 7907 Level: developer 7908 7909 .seealso DMPlexGetCellNumbering() 7910 @*/ 7911 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 7912 { 7913 IS nums[4]; 7914 PetscInt depths[4], gdepths[4], starts[4]; 7915 PetscInt depth, d, shift = 0; 7916 PetscErrorCode ierr; 7917 7918 PetscFunctionBegin; 7919 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7920 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7921 /* For unstratified meshes use dim instead of depth */ 7922 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 7923 for (d = 0; d <= depth; ++d) { 7924 PetscInt end; 7925 7926 depths[d] = depth-d; 7927 ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 7928 if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 7929 } 7930 ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 7931 ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 7932 for (d = 0; d <= depth; ++d) { 7933 if (starts[d] >= 0 && depths[d] != gdepths[d]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 7934 } 7935 for (d = 0; d <= depth; ++d) { 7936 PetscInt pStart, pEnd, gsize; 7937 7938 ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 7939 ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 7940 shift += gsize; 7941 } 7942 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 7943 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 7944 PetscFunctionReturn(0); 7945 } 7946 7947 /*@ 7948 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 7949 7950 Input Parameter: 7951 . dm - The DMPlex object 7952 7953 Output Parameter: 7954 . ranks - The rank field 7955 7956 Options Database Keys: 7957 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 7958 7959 Level: intermediate 7960 7961 .seealso: DMView() 7962 @*/ 7963 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 7964 { 7965 DM rdm; 7966 PetscFE fe; 7967 PetscScalar *r; 7968 PetscMPIInt rank; 7969 DMPolytopeType ct; 7970 PetscInt dim, cStart, cEnd, c; 7971 PetscBool simplex; 7972 PetscErrorCode ierr; 7973 7974 PetscFunctionBeginUser; 7975 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7976 PetscValidPointer(ranks, 2); 7977 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 7978 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 7979 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 7980 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7981 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 7982 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 7983 ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 7984 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 7985 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 7986 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 7987 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 7988 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 7989 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 7990 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 7991 for (c = cStart; c < cEnd; ++c) { 7992 PetscScalar *lr; 7993 7994 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 7995 if (lr) *lr = rank; 7996 } 7997 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 7998 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 7999 PetscFunctionReturn(0); 8000 } 8001 8002 /*@ 8003 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 8004 8005 Input Parameters: 8006 + dm - The DMPlex 8007 - label - The DMLabel 8008 8009 Output Parameter: 8010 . val - The label value field 8011 8012 Options Database Keys: 8013 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 8014 8015 Level: intermediate 8016 8017 .seealso: DMView() 8018 @*/ 8019 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8020 { 8021 DM rdm; 8022 PetscFE fe; 8023 PetscScalar *v; 8024 PetscInt dim, cStart, cEnd, c; 8025 PetscErrorCode ierr; 8026 8027 PetscFunctionBeginUser; 8028 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8029 PetscValidPointer(label, 2); 8030 PetscValidPointer(val, 3); 8031 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 8032 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 8033 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 8034 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 8035 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 8036 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 8037 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 8038 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8039 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 8040 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 8041 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 8042 for (c = cStart; c < cEnd; ++c) { 8043 PetscScalar *lv; 8044 PetscInt cval; 8045 8046 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 8047 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 8048 *lv = cval; 8049 } 8050 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 8051 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 8052 PetscFunctionReturn(0); 8053 } 8054 8055 /*@ 8056 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8057 8058 Input Parameter: 8059 . dm - The DMPlex object 8060 8061 Notes: 8062 This is a useful diagnostic when creating meshes programmatically. 8063 8064 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8065 8066 Level: developer 8067 8068 .seealso: DMCreate(), DMSetFromOptions() 8069 @*/ 8070 PetscErrorCode DMPlexCheckSymmetry(DM dm) 8071 { 8072 PetscSection coneSection, supportSection; 8073 const PetscInt *cone, *support; 8074 PetscInt coneSize, c, supportSize, s; 8075 PetscInt pStart, pEnd, p, pp, csize, ssize; 8076 PetscBool storagecheck = PETSC_TRUE; 8077 PetscErrorCode ierr; 8078 8079 PetscFunctionBegin; 8080 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8081 ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr); 8082 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 8083 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 8084 /* Check that point p is found in the support of its cone points, and vice versa */ 8085 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8086 for (p = pStart; p < pEnd; ++p) { 8087 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 8088 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 8089 for (c = 0; c < coneSize; ++c) { 8090 PetscBool dup = PETSC_FALSE; 8091 PetscInt d; 8092 for (d = c-1; d >= 0; --d) { 8093 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 8094 } 8095 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 8096 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 8097 for (s = 0; s < supportSize; ++s) { 8098 if (support[s] == p) break; 8099 } 8100 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 8101 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 8102 for (s = 0; s < coneSize; ++s) { 8103 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 8104 } 8105 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8106 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 8107 for (s = 0; s < supportSize; ++s) { 8108 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 8109 } 8110 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8111 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 8112 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 8113 } 8114 } 8115 ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 8116 if (p != pp) { storagecheck = PETSC_FALSE; continue; } 8117 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 8118 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 8119 for (s = 0; s < supportSize; ++s) { 8120 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 8121 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 8122 for (c = 0; c < coneSize; ++c) { 8123 ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 8124 if (cone[c] != pp) { c = 0; break; } 8125 if (cone[c] == p) break; 8126 } 8127 if (c >= coneSize) { 8128 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 8129 for (c = 0; c < supportSize; ++c) { 8130 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 8131 } 8132 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8133 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 8134 for (c = 0; c < coneSize; ++c) { 8135 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 8136 } 8137 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 8138 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 8139 } 8140 } 8141 } 8142 if (storagecheck) { 8143 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 8144 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 8145 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 8146 } 8147 PetscFunctionReturn(0); 8148 } 8149 8150 /* 8151 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. 8152 */ 8153 static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8154 { 8155 DMPolytopeType cct; 8156 PetscInt ptpoints[4]; 8157 const PetscInt *cone, *ccone, *ptcone; 8158 PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8159 PetscErrorCode ierr; 8160 8161 PetscFunctionBegin; 8162 *unsplit = 0; 8163 switch (ct) { 8164 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8165 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8166 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8167 for (cp = 0; cp < coneSize; ++cp) { 8168 ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr); 8169 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8170 } 8171 break; 8172 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8173 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8174 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8175 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8176 for (cp = 0; cp < coneSize; ++cp) { 8177 ierr = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr); 8178 ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr); 8179 for (ccp = 0; ccp < cconeSize; ++ccp) { 8180 ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr); 8181 if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8182 PetscInt p; 8183 for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 8184 if (p == npt) ptpoints[npt++] = ccone[ccp]; 8185 } 8186 } 8187 } 8188 break; 8189 default: break; 8190 } 8191 for (pt = 0; pt < npt; ++pt) { 8192 ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr); 8193 if (ptcone[0] == ptcone[1]) ++(*unsplit); 8194 } 8195 PetscFunctionReturn(0); 8196 } 8197 8198 /*@ 8199 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 8200 8201 Input Parameters: 8202 + dm - The DMPlex object 8203 - cellHeight - Normally 0 8204 8205 Notes: 8206 This is a useful diagnostic when creating meshes programmatically. 8207 Currently applicable only to homogeneous simplex or tensor meshes. 8208 8209 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8210 8211 Level: developer 8212 8213 .seealso: DMCreate(), DMSetFromOptions() 8214 @*/ 8215 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 8216 { 8217 DMPlexInterpolatedFlag interp; 8218 DMPolytopeType ct; 8219 PetscInt vStart, vEnd, cStart, cEnd, c; 8220 PetscErrorCode ierr; 8221 8222 PetscFunctionBegin; 8223 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8224 ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr); 8225 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8226 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8227 for (c = cStart; c < cEnd; ++c) { 8228 PetscInt *closure = NULL; 8229 PetscInt coneSize, closureSize, cl, Nv = 0; 8230 8231 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8232 if ((PetscInt) ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c); 8233 if (ct == DM_POLYTOPE_UNKNOWN) continue; 8234 if (interp == DMPLEX_INTERPOLATED_FULL) { 8235 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8236 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)); 8237 } 8238 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8239 for (cl = 0; cl < closureSize*2; cl += 2) { 8240 const PetscInt p = closure[cl]; 8241 if ((p >= vStart) && (p < vEnd)) ++Nv; 8242 } 8243 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8244 /* Special Case: Tensor faces with identified vertices */ 8245 if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 8246 PetscInt unsplit; 8247 8248 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8249 if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 8250 } 8251 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)); 8252 } 8253 PetscFunctionReturn(0); 8254 } 8255 8256 /*@ 8257 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 8258 8259 Not Collective 8260 8261 Input Parameters: 8262 + dm - The DMPlex object 8263 - cellHeight - Normally 0 8264 8265 Notes: 8266 This is a useful diagnostic when creating meshes programmatically. 8267 This routine is only relevant for meshes that are fully interpolated across all ranks. 8268 It will error out if a partially interpolated mesh is given on some rank. 8269 It will do nothing for locally uninterpolated mesh (as there is nothing to check). 8270 8271 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8272 8273 Level: developer 8274 8275 .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 8276 @*/ 8277 PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 8278 { 8279 PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 8280 PetscErrorCode ierr; 8281 DMPlexInterpolatedFlag interpEnum; 8282 8283 PetscFunctionBegin; 8284 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8285 ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr); 8286 if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 8287 if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 8288 PetscMPIInt rank; 8289 MPI_Comm comm; 8290 8291 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8292 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8293 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 8294 } 8295 8296 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8297 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8298 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8299 for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 8300 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 8301 for (c = cStart; c < cEnd; ++c) { 8302 const PetscInt *cone, *ornt, *faceSizes, *faces; 8303 const DMPolytopeType *faceTypes; 8304 DMPolytopeType ct; 8305 PetscInt numFaces, coneSize, f; 8306 PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 8307 8308 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8309 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8310 if (unsplit) continue; 8311 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8312 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 8313 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 8314 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8315 for (cl = 0; cl < closureSize*2; cl += 2) { 8316 const PetscInt p = closure[cl]; 8317 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 8318 } 8319 ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8320 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); 8321 for (f = 0; f < numFaces; ++f) { 8322 DMPolytopeType fct; 8323 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 8324 8325 ierr = DMPlexGetCellType(dm, cone[f], &fct);CHKERRQ(ierr); 8326 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8327 for (cl = 0; cl < fclosureSize*2; cl += 2) { 8328 const PetscInt p = fclosure[cl]; 8329 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 8330 } 8331 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]); 8332 for (v = 0; v < fnumCorners; ++v) { 8333 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]); 8334 } 8335 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 8336 fOff += faceSizes[f]; 8337 } 8338 ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 8339 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8340 } 8341 } 8342 PetscFunctionReturn(0); 8343 } 8344 8345 /*@ 8346 DMPlexCheckGeometry - Check the geometry of mesh cells 8347 8348 Input Parameter: 8349 . dm - The DMPlex object 8350 8351 Notes: 8352 This is a useful diagnostic when creating meshes programmatically. 8353 8354 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8355 8356 Level: developer 8357 8358 .seealso: DMCreate(), DMSetFromOptions() 8359 @*/ 8360 PetscErrorCode DMPlexCheckGeometry(DM dm) 8361 { 8362 Vec coordinates; 8363 PetscReal detJ, J[9], refVol = 1.0; 8364 PetscReal vol; 8365 PetscBool periodic; 8366 PetscInt dim, depth, dE, d, cStart, cEnd, c; 8367 PetscErrorCode ierr; 8368 8369 PetscFunctionBegin; 8370 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8371 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 8372 if (dim != dE) PetscFunctionReturn(0); 8373 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 8374 ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr); 8375 for (d = 0; d < dim; ++d) refVol *= 2.0; 8376 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8377 /* Make sure local coordinates are created, because that step is collective */ 8378 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8379 for (c = cStart; c < cEnd; ++c) { 8380 DMPolytopeType ct; 8381 PetscInt unsplit; 8382 PetscBool ignoreZeroVol = PETSC_FALSE; 8383 8384 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 8385 switch (ct) { 8386 case DM_POLYTOPE_SEG_PRISM_TENSOR: 8387 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8388 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8389 ignoreZeroVol = PETSC_TRUE; break; 8390 default: break; 8391 } 8392 switch (ct) { 8393 case DM_POLYTOPE_TRI_PRISM: 8394 case DM_POLYTOPE_TRI_PRISM_TENSOR: 8395 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 8396 case DM_POLYTOPE_PYRAMID: 8397 continue; 8398 default: break; 8399 } 8400 ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 8401 if (unsplit) continue; 8402 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 8403 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); 8404 ierr = PetscInfo2(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 8405 if (depth > 1 && !periodic) { 8406 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 8407 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); 8408 ierr = PetscInfo2(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 8409 } 8410 } 8411 PetscFunctionReturn(0); 8412 } 8413 8414 /*@ 8415 DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 8416 8417 Input Parameters: 8418 . dm - The DMPlex object 8419 8420 Notes: 8421 This is mainly intended for debugging/testing purposes. 8422 It currently checks only meshes with no partition overlapping. 8423 8424 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8425 8426 Level: developer 8427 8428 .seealso: DMGetPointSF(), DMSetFromOptions() 8429 @*/ 8430 PetscErrorCode DMPlexCheckPointSF(DM dm) 8431 { 8432 PetscSF pointSF; 8433 PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 8434 const PetscInt *locals, *rootdegree; 8435 PetscBool distributed; 8436 PetscErrorCode ierr; 8437 8438 PetscFunctionBegin; 8439 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8440 ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr); 8441 ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 8442 if (!distributed) PetscFunctionReturn(0); 8443 ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 8444 if (overlap) { 8445 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping");CHKERRQ(ierr); 8446 PetscFunctionReturn(0); 8447 } 8448 if (!pointSF) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 8449 ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr); 8450 if (nroots < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 8451 ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 8452 ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 8453 8454 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 8455 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8456 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8457 for (l = 0; l < nleaves; ++l) { 8458 const PetscInt point = locals[l]; 8459 8460 if (point >= cStart && point < cEnd) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 8461 } 8462 8463 /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 8464 for (l = 0; l < nleaves; ++l) { 8465 const PetscInt point = locals[l]; 8466 const PetscInt *cone; 8467 PetscInt coneSize, c, idx; 8468 8469 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 8470 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 8471 for (c = 0; c < coneSize; ++c) { 8472 if (!rootdegree[cone[c]]) { 8473 ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr); 8474 if (idx < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 8475 } 8476 } 8477 } 8478 PetscFunctionReturn(0); 8479 } 8480 8481 typedef struct cell_stats 8482 { 8483 PetscReal min, max, sum, squaresum; 8484 PetscInt count; 8485 } cell_stats_t; 8486 8487 static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 8488 { 8489 PetscInt i, N = *len; 8490 8491 for (i = 0; i < N; i++) { 8492 cell_stats_t *A = (cell_stats_t *) a; 8493 cell_stats_t *B = (cell_stats_t *) b; 8494 8495 B->min = PetscMin(A->min,B->min); 8496 B->max = PetscMax(A->max,B->max); 8497 B->sum += A->sum; 8498 B->squaresum += A->squaresum; 8499 B->count += A->count; 8500 } 8501 } 8502 8503 /*@ 8504 DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 8505 8506 Collective on dm 8507 8508 Input Parameters: 8509 + dm - The DMPlex object 8510 . output - If true, statistics will be displayed on stdout 8511 - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 8512 8513 Notes: 8514 This is mainly intended for debugging/testing purposes. 8515 8516 For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 8517 8518 Level: developer 8519 8520 .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality() 8521 @*/ 8522 PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 8523 { 8524 DM dmCoarse; 8525 cell_stats_t stats, globalStats; 8526 MPI_Comm comm = PetscObjectComm((PetscObject)dm); 8527 PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 8528 PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 8529 PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 8530 PetscMPIInt rank,size; 8531 PetscErrorCode ierr; 8532 8533 PetscFunctionBegin; 8534 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8535 stats.min = PETSC_MAX_REAL; 8536 stats.max = PETSC_MIN_REAL; 8537 stats.sum = stats.squaresum = 0.; 8538 stats.count = 0; 8539 8540 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 8541 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8542 ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr); 8543 ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr); 8544 ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 8545 ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); 8546 for (c = cStart; c < cEnd; c++) { 8547 PetscInt i; 8548 PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 8549 8550 ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 8551 if (detJ < 0.0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 8552 for (i = 0; i < PetscSqr(cdim); ++i) { 8553 frobJ += J[i] * J[i]; 8554 frobInvJ += invJ[i] * invJ[i]; 8555 } 8556 cond2 = frobJ * frobInvJ; 8557 cond = PetscSqrtReal(cond2); 8558 8559 stats.min = PetscMin(stats.min,cond); 8560 stats.max = PetscMax(stats.max,cond); 8561 stats.sum += cond; 8562 stats.squaresum += cond2; 8563 stats.count++; 8564 if (output && cond > limit) { 8565 PetscSection coordSection; 8566 Vec coordsLocal; 8567 PetscScalar *coords = NULL; 8568 PetscInt Nv, d, clSize, cl, *closure = NULL; 8569 8570 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8571 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8572 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8573 ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr); 8574 for (i = 0; i < Nv/cdim; ++i) { 8575 ierr = PetscSynchronizedPrintf(comm, " Vertex %D: (", i);CHKERRQ(ierr); 8576 for (d = 0; d < cdim; ++d) { 8577 if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);} 8578 ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr); 8579 } 8580 ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr); 8581 } 8582 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8583 for (cl = 0; cl < clSize*2; cl += 2) { 8584 const PetscInt edge = closure[cl]; 8585 8586 if ((edge >= eStart) && (edge < eEnd)) { 8587 PetscReal len; 8588 8589 ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr); 8590 ierr = PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr); 8591 } 8592 } 8593 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 8594 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 8595 } 8596 } 8597 if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 8598 8599 if (size > 1) { 8600 PetscMPIInt blockLengths[2] = {4,1}; 8601 MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 8602 MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 8603 MPI_Op statReduce; 8604 8605 ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRMPI(ierr); 8606 ierr = MPI_Type_commit(&statType);CHKERRMPI(ierr); 8607 ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRMPI(ierr); 8608 ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRMPI(ierr); 8609 ierr = MPI_Op_free(&statReduce);CHKERRMPI(ierr); 8610 ierr = MPI_Type_free(&statType);CHKERRMPI(ierr); 8611 } else { 8612 ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr); 8613 } 8614 if (!rank) { 8615 count = globalStats.count; 8616 min = globalStats.min; 8617 max = globalStats.max; 8618 mean = globalStats.sum / globalStats.count; 8619 stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 8620 } 8621 8622 if (output) { 8623 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); 8624 } 8625 ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 8626 8627 ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 8628 if (dmCoarse) { 8629 PetscBool isplex; 8630 8631 ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 8632 if (isplex) { 8633 ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr); 8634 } 8635 } 8636 PetscFunctionReturn(0); 8637 } 8638 8639 /*@ 8640 DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 8641 orthogonal quality below given tolerance. 8642 8643 Collective on dm 8644 8645 Input Parameters: 8646 + dm - The DMPlex object 8647 . fv - Optional PetscFV object for pre-computed cell/face centroid information 8648 - atol - [0, 1] Absolute tolerance for tagging cells. 8649 8650 Output Parameters: 8651 + OrthQual - Vec containing orthogonal quality per cell 8652 - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE 8653 8654 Options Database Keys: 8655 + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is 8656 supported. 8657 - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 8658 8659 Notes: 8660 Orthogonal quality is given by the following formula: 8661 8662 \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right] 8663 8664 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 8665 is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 8666 current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 8667 calculating the cosine of the angle between these vectors. 8668 8669 Orthogonal quality ranges from 1 (best) to 0 (worst). 8670 8671 This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for 8672 pre-computed FVM cell data, but if it is not passed in then this data will be computed. 8673 8674 Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 8675 8676 Level: intermediate 8677 8678 .seealso: DMPlexCheckCellShape(), DMCreateLabel() 8679 @*/ 8680 PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 8681 { 8682 PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 8683 PetscInt *idx; 8684 PetscScalar *oqVals; 8685 const PetscScalar *cellGeomArr, *faceGeomArr; 8686 PetscReal *ci, *fi, *Ai; 8687 MPI_Comm comm; 8688 Vec cellgeom, facegeom; 8689 DM dmFace, dmCell; 8690 IS glob; 8691 ISLocalToGlobalMapping ltog; 8692 PetscViewer vwr; 8693 PetscErrorCode ierr; 8694 8695 PetscFunctionBegin; 8696 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8697 if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);} 8698 PetscValidPointer(OrthQual, 4); 8699 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); 8700 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 8701 ierr = DMGetDimension(dm, &nc);CHKERRQ(ierr); 8702 if (nc < 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc); 8703 { 8704 DMPlexInterpolatedFlag interpFlag; 8705 8706 ierr = DMPlexIsInterpolated(dm, &interpFlag);CHKERRQ(ierr); 8707 if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 8708 PetscMPIInt rank; 8709 8710 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8711 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 8712 } 8713 } 8714 if (OrthQualLabel) { 8715 PetscValidPointer(OrthQualLabel, 5); 8716 ierr = DMCreateLabel(dm, "Orthogonal_Quality");CHKERRQ(ierr); 8717 ierr = DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel);CHKERRQ(ierr); 8718 } else {*OrthQualLabel = NULL;} 8719 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8720 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8721 ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob);CHKERRQ(ierr); 8722 ierr = ISLocalToGlobalMappingCreateIS(glob, <og);CHKERRQ(ierr); 8723 ierr = ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 8724 ierr = VecCreate(comm, OrthQual);CHKERRQ(ierr); 8725 ierr = VecSetType(*OrthQual, VECSTANDARD);CHKERRQ(ierr); 8726 ierr = VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr); 8727 ierr = VecSetLocalToGlobalMapping(*OrthQual, ltog);CHKERRQ(ierr); 8728 ierr = VecSetUp(*OrthQual);CHKERRQ(ierr); 8729 ierr = ISDestroy(&glob);CHKERRQ(ierr); 8730 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 8731 ierr = DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL);CHKERRQ(ierr); 8732 ierr = VecGetArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8733 ierr = VecGetArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8734 ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr); 8735 ierr = VecGetDM(facegeom, &dmFace);CHKERRQ(ierr); 8736 ierr = PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai);CHKERRQ(ierr); 8737 for (cell = cStart; cell < cEnd; cellIter++,cell++) { 8738 PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 8739 PetscInt cellarr[2], *adj = NULL; 8740 PetscScalar *cArr, *fArr; 8741 PetscReal minvalc = 1.0, minvalf = 1.0; 8742 PetscFVCellGeom *cg; 8743 8744 idx[cellIter] = cell-cStart; 8745 cellarr[0] = cell; 8746 /* Make indexing into cellGeom easier */ 8747 ierr = DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg);CHKERRQ(ierr); 8748 ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj);CHKERRQ(ierr); 8749 /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 8750 ierr = PetscCalloc2(adjSize, &cArr, adjSize, &fArr);CHKERRQ(ierr); 8751 for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) { 8752 PetscInt i; 8753 const PetscInt neigh = adj[cellneigh]; 8754 PetscReal normci = 0, normfi = 0, normai = 0; 8755 PetscFVCellGeom *cgneigh; 8756 PetscFVFaceGeom *fg; 8757 8758 /* Don't count ourselves in the neighbor list */ 8759 if (neigh == cell) continue; 8760 ierr = DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh);CHKERRQ(ierr); 8761 cellarr[1] = neigh; 8762 { 8763 PetscInt numcovpts; 8764 const PetscInt *covpts; 8765 8766 ierr = DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 8767 ierr = DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg);CHKERRQ(ierr); 8768 ierr = DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr); 8769 } 8770 8771 /* Compute c_i, f_i and their norms */ 8772 for (i = 0; i < nc; i++) { 8773 ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 8774 fi[i] = fg->centroid[i] - cg->centroid[i]; 8775 Ai[i] = fg->normal[i]; 8776 normci += PetscPowReal(ci[i], 2); 8777 normfi += PetscPowReal(fi[i], 2); 8778 normai += PetscPowReal(Ai[i], 2); 8779 } 8780 normci = PetscSqrtReal(normci); 8781 normfi = PetscSqrtReal(normfi); 8782 normai = PetscSqrtReal(normai); 8783 8784 /* Normalize and compute for each face-cell-normal pair */ 8785 for (i = 0; i < nc; i++) { 8786 ci[i] = ci[i]/normci; 8787 fi[i] = fi[i]/normfi; 8788 Ai[i] = Ai[i]/normai; 8789 /* PetscAbs because I don't know if normals are guaranteed to point out */ 8790 cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]); 8791 fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]); 8792 } 8793 if (PetscRealPart(cArr[cellneighiter]) < minvalc) { 8794 minvalc = PetscRealPart(cArr[cellneighiter]); 8795 } 8796 if (PetscRealPart(fArr[cellneighiter]) < minvalf) { 8797 minvalf = PetscRealPart(fArr[cellneighiter]); 8798 } 8799 } 8800 ierr = PetscFree(adj);CHKERRQ(ierr); 8801 ierr = PetscFree2(cArr, fArr);CHKERRQ(ierr); 8802 /* Defer to cell if they're equal */ 8803 oqVals[cellIter] = PetscMin(minvalf, minvalc); 8804 if (OrthQualLabel) { 8805 if (PetscRealPart(oqVals[cellIter]) <= atol) {ierr = DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE);CHKERRQ(ierr);} 8806 } 8807 } 8808 ierr = VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES);CHKERRQ(ierr); 8809 ierr = VecAssemblyBegin(*OrthQual);CHKERRQ(ierr); 8810 ierr = VecAssemblyEnd(*OrthQual);CHKERRQ(ierr); 8811 ierr = VecRestoreArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr); 8812 ierr = VecRestoreArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr); 8813 ierr = PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL);CHKERRQ(ierr); 8814 if (OrthQualLabel) { 8815 if (vwr) {ierr = DMLabelView(*OrthQualLabel, vwr);CHKERRQ(ierr);} 8816 } 8817 ierr = PetscFree5(idx, oqVals, ci, fi, Ai);CHKERRQ(ierr); 8818 ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr); 8819 ierr = VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view");CHKERRQ(ierr); 8820 PetscFunctionReturn(0); 8821 } 8822 8823 /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect 8824 * interpolator construction */ 8825 static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 8826 { 8827 PetscSection section, newSection, gsection; 8828 PetscSF sf; 8829 PetscBool hasConstraints, ghasConstraints; 8830 PetscErrorCode ierr; 8831 8832 PetscFunctionBegin; 8833 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8834 PetscValidPointer(odm,2); 8835 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 8836 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 8837 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 8838 if (!ghasConstraints) { 8839 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 8840 *odm = dm; 8841 PetscFunctionReturn(0); 8842 } 8843 ierr = DMClone(dm, odm);CHKERRQ(ierr); 8844 ierr = DMCopyFields(dm, *odm);CHKERRQ(ierr); 8845 ierr = DMGetLocalSection(*odm, &newSection);CHKERRQ(ierr); 8846 ierr = DMGetPointSF(*odm, &sf);CHKERRQ(ierr); 8847 ierr = PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 8848 ierr = DMSetGlobalSection(*odm, gsection);CHKERRQ(ierr); 8849 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 8850 PetscFunctionReturn(0); 8851 } 8852 8853 static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 8854 { 8855 DM dmco, dmfo; 8856 Mat interpo; 8857 Vec rscale; 8858 Vec cglobalo, clocal; 8859 Vec fglobal, fglobalo, flocal; 8860 PetscBool regular; 8861 PetscErrorCode ierr; 8862 8863 PetscFunctionBegin; 8864 ierr = DMGetFullDM(dmc, &dmco);CHKERRQ(ierr); 8865 ierr = DMGetFullDM(dmf, &dmfo);CHKERRQ(ierr); 8866 ierr = DMSetCoarseDM(dmfo, dmco);CHKERRQ(ierr); 8867 ierr = DMPlexGetRegularRefinement(dmf, ®ular);CHKERRQ(ierr); 8868 ierr = DMPlexSetRegularRefinement(dmfo, regular);CHKERRQ(ierr); 8869 ierr = DMCreateInterpolation(dmco, dmfo, &interpo, &rscale);CHKERRQ(ierr); 8870 ierr = DMCreateGlobalVector(dmco, &cglobalo);CHKERRQ(ierr); 8871 ierr = DMCreateLocalVector(dmc, &clocal);CHKERRQ(ierr); 8872 ierr = VecSet(cglobalo, 0.);CHKERRQ(ierr); 8873 ierr = VecSet(clocal, 0.);CHKERRQ(ierr); 8874 ierr = DMCreateGlobalVector(dmf, &fglobal);CHKERRQ(ierr); 8875 ierr = DMCreateGlobalVector(dmfo, &fglobalo);CHKERRQ(ierr); 8876 ierr = DMCreateLocalVector(dmf, &flocal);CHKERRQ(ierr); 8877 ierr = VecSet(fglobal, 0.);CHKERRQ(ierr); 8878 ierr = VecSet(fglobalo, 0.);CHKERRQ(ierr); 8879 ierr = VecSet(flocal, 0.);CHKERRQ(ierr); 8880 ierr = DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL);CHKERRQ(ierr); 8881 ierr = DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 8882 ierr = DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr); 8883 ierr = MatMult(interpo, cglobalo, fglobalo);CHKERRQ(ierr); 8884 ierr = DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 8885 ierr = DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr); 8886 ierr = DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 8887 ierr = DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr); 8888 *shift = fglobal; 8889 ierr = VecDestroy(&flocal);CHKERRQ(ierr); 8890 ierr = VecDestroy(&fglobalo);CHKERRQ(ierr); 8891 ierr = VecDestroy(&clocal);CHKERRQ(ierr); 8892 ierr = VecDestroy(&cglobalo);CHKERRQ(ierr); 8893 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 8894 ierr = MatDestroy(&interpo);CHKERRQ(ierr); 8895 ierr = DMDestroy(&dmfo);CHKERRQ(ierr); 8896 ierr = DMDestroy(&dmco);CHKERRQ(ierr); 8897 PetscFunctionReturn(0); 8898 } 8899 8900 PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 8901 { 8902 PetscObject shifto; 8903 Vec shift; 8904 8905 PetscErrorCode ierr; 8906 8907 PetscFunctionBegin; 8908 if (!interp) { 8909 Vec rscale; 8910 8911 ierr = DMCreateInterpolation(coarse, fine, &interp, &rscale);CHKERRQ(ierr); 8912 ierr = VecDestroy(&rscale);CHKERRQ(ierr); 8913 } else { 8914 ierr = PetscObjectReference((PetscObject)interp);CHKERRQ(ierr); 8915 } 8916 ierr = PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto);CHKERRQ(ierr); 8917 if (!shifto) { 8918 ierr = DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift);CHKERRQ(ierr); 8919 ierr = PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift);CHKERRQ(ierr); 8920 shifto = (PetscObject) shift; 8921 ierr = VecDestroy(&shift);CHKERRQ(ierr); 8922 } 8923 shift = (Vec) shifto; 8924 ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr); 8925 ierr = VecAXPY(fineSol, 1.0, shift);CHKERRQ(ierr); 8926 ierr = MatDestroy(&interp);CHKERRQ(ierr); 8927 PetscFunctionReturn(0); 8928 } 8929 8930 /* Pointwise interpolation 8931 Just code FEM for now 8932 u^f = I u^c 8933 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 8934 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 8935 I_{ij} = psi^f_i phi^c_j 8936 */ 8937 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 8938 { 8939 PetscSection gsc, gsf; 8940 PetscInt m, n; 8941 void *ctx; 8942 DM cdm; 8943 PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 8944 PetscErrorCode ierr; 8945 8946 PetscFunctionBegin; 8947 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 8948 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 8949 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 8950 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 8951 8952 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 8953 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 8954 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 8955 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 8956 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 8957 8958 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 8959 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 8960 if (!isRefined || (regular && cdm == dmCoarse)) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx);CHKERRQ(ierr);} 8961 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 8962 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 8963 if (scaling) { 8964 /* Use naive scaling */ 8965 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 8966 } 8967 PetscFunctionReturn(0); 8968 } 8969 8970 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 8971 { 8972 PetscErrorCode ierr; 8973 VecScatter ctx; 8974 8975 PetscFunctionBegin; 8976 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 8977 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 8978 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 8979 PetscFunctionReturn(0); 8980 } 8981 8982 static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8983 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8984 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8985 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 8986 { 8987 g0[0] = 1.0; 8988 } 8989 8990 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 8991 { 8992 PetscSection gsc, gsf; 8993 PetscInt m, n; 8994 void *ctx; 8995 DM cdm; 8996 PetscBool regular; 8997 PetscErrorCode ierr; 8998 8999 PetscFunctionBegin; 9000 if (dmFine == dmCoarse) { 9001 DM dmc; 9002 PetscDS ds; 9003 Vec u; 9004 IS cellIS; 9005 PetscFormKey key; 9006 PetscInt depth; 9007 9008 ierr = DMClone(dmFine, &dmc);CHKERRQ(ierr); 9009 ierr = DMCopyDisc(dmFine, dmc);CHKERRQ(ierr); 9010 ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr); 9011 ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr); 9012 ierr = DMCreateMatrix(dmc, mass);CHKERRQ(ierr); 9013 ierr = DMGetGlobalVector(dmc, &u);CHKERRQ(ierr); 9014 ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr); 9015 ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr); 9016 ierr = MatZeroEntries(*mass);CHKERRQ(ierr); 9017 key.label = NULL; 9018 key.value = 0; 9019 key.field = 0; 9020 key.part = 0; 9021 ierr = DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL);CHKERRQ(ierr); 9022 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 9023 ierr = DMRestoreGlobalVector(dmc, &u);CHKERRQ(ierr); 9024 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 9025 } else { 9026 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 9027 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 9028 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 9029 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 9030 9031 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 9032 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 9033 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 9034 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 9035 9036 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 9037 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 9038 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9039 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 9040 } 9041 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 9042 PetscFunctionReturn(0); 9043 } 9044 9045 /*@ 9046 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9047 9048 Input Parameter: 9049 . dm - The DMPlex object 9050 9051 Output Parameter: 9052 . regular - The flag 9053 9054 Level: intermediate 9055 9056 .seealso: DMPlexSetRegularRefinement() 9057 @*/ 9058 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 9059 { 9060 PetscFunctionBegin; 9061 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9062 PetscValidPointer(regular, 2); 9063 *regular = ((DM_Plex *) dm->data)->regularRefinement; 9064 PetscFunctionReturn(0); 9065 } 9066 9067 /*@ 9068 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 9069 9070 Input Parameters: 9071 + dm - The DMPlex object 9072 - regular - The flag 9073 9074 Level: intermediate 9075 9076 .seealso: DMPlexGetRegularRefinement() 9077 @*/ 9078 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 9079 { 9080 PetscFunctionBegin; 9081 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9082 ((DM_Plex *) dm->data)->regularRefinement = regular; 9083 PetscFunctionReturn(0); 9084 } 9085 9086 /*@ 9087 DMPlexGetCellRefinerType - Get the strategy for refining a cell 9088 9089 Input Parameter: 9090 . dm - The DMPlex object 9091 9092 Output Parameter: 9093 . cr - The strategy number 9094 9095 Level: intermediate 9096 9097 .seealso: DMPlexSetCellRefinerType(), DMPlexSetRegularRefinement() 9098 @*/ 9099 PetscErrorCode DMPlexGetCellRefinerType(DM dm, DMPlexCellRefinerType *cr) 9100 { 9101 PetscFunctionBegin; 9102 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9103 PetscValidPointer(cr, 2); 9104 *cr = ((DM_Plex *) dm->data)->cellRefiner; 9105 PetscFunctionReturn(0); 9106 } 9107 9108 /*@ 9109 DMPlexSetCellRefinerType - Set the strategy for refining a cell 9110 9111 Input Parameters: 9112 + dm - The DMPlex object 9113 - cr - The strategy number 9114 9115 Level: intermediate 9116 9117 .seealso: DMPlexGetCellRefinerType(), DMPlexGetRegularRefinement() 9118 @*/ 9119 PetscErrorCode DMPlexSetCellRefinerType(DM dm, DMPlexCellRefinerType cr) 9120 { 9121 PetscFunctionBegin; 9122 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9123 ((DM_Plex *) dm->data)->cellRefiner = cr; 9124 PetscFunctionReturn(0); 9125 } 9126 9127 /* anchors */ 9128 /*@ 9129 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9130 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 9131 9132 not collective 9133 9134 Input Parameters: 9135 . dm - The DMPlex object 9136 9137 Output Parameters: 9138 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 9139 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 9140 9141 Level: intermediate 9142 9143 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 9144 @*/ 9145 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 9146 { 9147 DM_Plex *plex = (DM_Plex *)dm->data; 9148 PetscErrorCode ierr; 9149 9150 PetscFunctionBegin; 9151 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9152 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 9153 if (anchorSection) *anchorSection = plex->anchorSection; 9154 if (anchorIS) *anchorIS = plex->anchorIS; 9155 PetscFunctionReturn(0); 9156 } 9157 9158 /*@ 9159 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 9160 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 9161 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 9162 9163 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 9164 DMGetConstraints() and filling in the entries in the constraint matrix. 9165 9166 collective on dm 9167 9168 Input Parameters: 9169 + dm - The DMPlex object 9170 . 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). 9171 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 9172 9173 The reference counts of anchorSection and anchorIS are incremented. 9174 9175 Level: intermediate 9176 9177 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 9178 @*/ 9179 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 9180 { 9181 DM_Plex *plex = (DM_Plex *)dm->data; 9182 PetscMPIInt result; 9183 PetscErrorCode ierr; 9184 9185 PetscFunctionBegin; 9186 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9187 if (anchorSection) { 9188 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 9189 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRMPI(ierr); 9190 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 9191 } 9192 if (anchorIS) { 9193 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 9194 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRMPI(ierr); 9195 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 9196 } 9197 9198 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 9199 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 9200 plex->anchorSection = anchorSection; 9201 9202 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 9203 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 9204 plex->anchorIS = anchorIS; 9205 9206 if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 9207 PetscInt size, a, pStart, pEnd; 9208 const PetscInt *anchors; 9209 9210 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9211 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 9212 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 9213 for (a = 0; a < size; a++) { 9214 PetscInt p; 9215 9216 p = anchors[a]; 9217 if (p >= pStart && p < pEnd) { 9218 PetscInt dof; 9219 9220 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9221 if (dof) { 9222 PetscErrorCode ierr2; 9223 9224 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 9225 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 9226 } 9227 } 9228 } 9229 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 9230 } 9231 /* reset the generic constraints */ 9232 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 9233 PetscFunctionReturn(0); 9234 } 9235 9236 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 9237 { 9238 PetscSection anchorSection; 9239 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 9240 PetscErrorCode ierr; 9241 9242 PetscFunctionBegin; 9243 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9244 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9245 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 9246 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9247 if (numFields) { 9248 PetscInt f; 9249 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 9250 9251 for (f = 0; f < numFields; f++) { 9252 PetscInt numComp; 9253 9254 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 9255 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 9256 } 9257 } 9258 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 9259 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9260 pStart = PetscMax(pStart,sStart); 9261 pEnd = PetscMin(pEnd,sEnd); 9262 pEnd = PetscMax(pStart,pEnd); 9263 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 9264 for (p = pStart; p < pEnd; p++) { 9265 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 9266 if (dof) { 9267 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 9268 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 9269 for (f = 0; f < numFields; f++) { 9270 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 9271 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 9272 } 9273 } 9274 } 9275 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 9276 ierr = PetscObjectSetName((PetscObject) *cSec, "Constraint Section");CHKERRQ(ierr); 9277 PetscFunctionReturn(0); 9278 } 9279 9280 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 9281 { 9282 PetscSection aSec; 9283 PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 9284 const PetscInt *anchors; 9285 PetscInt numFields, f; 9286 IS aIS; 9287 PetscErrorCode ierr; 9288 MatType mtype; 9289 PetscBool iscuda,iskokkos; 9290 9291 PetscFunctionBegin; 9292 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9293 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 9294 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 9295 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 9296 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 9297 ierr = PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr); 9298 if (!iscuda) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr); } 9299 ierr = PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos);CHKERRQ(ierr); 9300 if (!iskokkos) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos);CHKERRQ(ierr); } 9301 if (iscuda) mtype = MATSEQAIJCUSPARSE; 9302 else if (iskokkos) mtype = MATSEQAIJKOKKOS; 9303 else mtype = MATSEQAIJ; 9304 ierr = MatSetType(*cMat,mtype);CHKERRQ(ierr); 9305 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 9306 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 9307 /* cSec will be a subset of aSec and section */ 9308 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 9309 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 9310 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 9311 i[0] = 0; 9312 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 9313 for (p = pStart; p < pEnd; p++) { 9314 PetscInt rDof, rOff, r; 9315 9316 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9317 if (!rDof) continue; 9318 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9319 if (numFields) { 9320 for (f = 0; f < numFields; f++) { 9321 annz = 0; 9322 for (r = 0; r < rDof; r++) { 9323 a = anchors[rOff + r]; 9324 if (a < sStart || a >= sEnd) continue; 9325 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9326 annz += aDof; 9327 } 9328 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9329 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 9330 for (q = 0; q < dof; q++) { 9331 i[off + q + 1] = i[off + q] + annz; 9332 } 9333 } 9334 } 9335 else { 9336 annz = 0; 9337 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9338 for (q = 0; q < dof; q++) { 9339 a = anchors[rOff + q]; 9340 if (a < sStart || a >= sEnd) continue; 9341 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9342 annz += aDof; 9343 } 9344 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9345 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 9346 for (q = 0; q < dof; q++) { 9347 i[off + q + 1] = i[off + q] + annz; 9348 } 9349 } 9350 } 9351 nnz = i[m]; 9352 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 9353 offset = 0; 9354 for (p = pStart; p < pEnd; p++) { 9355 if (numFields) { 9356 for (f = 0; f < numFields; f++) { 9357 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 9358 for (q = 0; q < dof; q++) { 9359 PetscInt rDof, rOff, r; 9360 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9361 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9362 for (r = 0; r < rDof; r++) { 9363 PetscInt s; 9364 9365 a = anchors[rOff + r]; 9366 if (a < sStart || a >= sEnd) continue; 9367 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 9368 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 9369 for (s = 0; s < aDof; s++) { 9370 j[offset++] = aOff + s; 9371 } 9372 } 9373 } 9374 } 9375 } 9376 else { 9377 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 9378 for (q = 0; q < dof; q++) { 9379 PetscInt rDof, rOff, r; 9380 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 9381 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 9382 for (r = 0; r < rDof; r++) { 9383 PetscInt s; 9384 9385 a = anchors[rOff + r]; 9386 if (a < sStart || a >= sEnd) continue; 9387 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 9388 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 9389 for (s = 0; s < aDof; s++) { 9390 j[offset++] = aOff + s; 9391 } 9392 } 9393 } 9394 } 9395 } 9396 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 9397 ierr = PetscFree(i);CHKERRQ(ierr); 9398 ierr = PetscFree(j);CHKERRQ(ierr); 9399 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 9400 PetscFunctionReturn(0); 9401 } 9402 9403 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 9404 { 9405 DM_Plex *plex = (DM_Plex *)dm->data; 9406 PetscSection anchorSection, section, cSec; 9407 Mat cMat; 9408 PetscErrorCode ierr; 9409 9410 PetscFunctionBegin; 9411 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9412 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 9413 if (anchorSection) { 9414 PetscInt Nf; 9415 9416 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 9417 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 9418 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 9419 ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 9420 if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 9421 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 9422 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 9423 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 9424 } 9425 PetscFunctionReturn(0); 9426 } 9427 9428 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 9429 { 9430 IS subis; 9431 PetscSection section, subsection; 9432 PetscErrorCode ierr; 9433 9434 PetscFunctionBegin; 9435 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 9436 if (!section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 9437 if (!subdm) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 9438 /* Create subdomain */ 9439 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 9440 /* Create submodel */ 9441 ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr); 9442 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 9443 ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr); 9444 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 9445 ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 9446 /* Create map from submodel to global model */ 9447 if (is) { 9448 PetscSection sectionGlobal, subsectionGlobal; 9449 IS spIS; 9450 const PetscInt *spmap; 9451 PetscInt *subIndices; 9452 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 9453 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 9454 9455 ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 9456 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 9457 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 9458 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 9459 ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 9460 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 9461 for (p = pStart; p < pEnd; ++p) { 9462 PetscInt gdof, pSubSize = 0; 9463 9464 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 9465 if (gdof > 0) { 9466 for (f = 0; f < Nf; ++f) { 9467 PetscInt fdof, fcdof; 9468 9469 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 9470 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 9471 pSubSize += fdof-fcdof; 9472 } 9473 subSize += pSubSize; 9474 if (pSubSize) { 9475 if (bs < 0) { 9476 bs = pSubSize; 9477 } else if (bs != pSubSize) { 9478 /* Layout does not admit a pointwise block size */ 9479 bs = 1; 9480 } 9481 } 9482 } 9483 } 9484 /* Must have same blocksize on all procs (some might have no points) */ 9485 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 9486 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 9487 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 9488 else {bs = bsMinMax[0];} 9489 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 9490 for (p = pStart; p < pEnd; ++p) { 9491 PetscInt gdof, goff; 9492 9493 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 9494 if (gdof > 0) { 9495 const PetscInt point = spmap[p]; 9496 9497 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 9498 for (f = 0; f < Nf; ++f) { 9499 PetscInt fdof, fcdof, fc, f2, poff = 0; 9500 9501 /* Can get rid of this loop by storing field information in the global section */ 9502 for (f2 = 0; f2 < f; ++f2) { 9503 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 9504 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 9505 poff += fdof-fcdof; 9506 } 9507 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 9508 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 9509 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 9510 subIndices[subOff] = goff+poff+fc; 9511 } 9512 } 9513 } 9514 } 9515 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 9516 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 9517 if (bs > 1) { 9518 /* We need to check that the block size does not come from non-contiguous fields */ 9519 PetscInt i, j, set = 1; 9520 for (i = 0; i < subSize; i += bs) { 9521 for (j = 0; j < bs; ++j) { 9522 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 9523 } 9524 } 9525 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 9526 } 9527 /* Attach nullspace */ 9528 for (f = 0; f < Nf; ++f) { 9529 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 9530 if ((*subdm)->nullspaceConstructors[f]) break; 9531 } 9532 if (f < Nf) { 9533 MatNullSpace nullSpace; 9534 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace);CHKERRQ(ierr); 9535 9536 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 9537 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 9538 } 9539 } 9540 PetscFunctionReturn(0); 9541 } 9542 9543 /*@ 9544 DMPlexMonitorThroughput - Report the cell throughput of FE integration 9545 9546 Input Parameter: 9547 - dm - The DM 9548 9549 Level: developer 9550 9551 Options Database Keys: 9552 . -dm_plex_monitor_throughput - Activate the monitor 9553 9554 .seealso: DMSetFromOptions(), DMPlexCreate() 9555 @*/ 9556 PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 9557 { 9558 #if defined(PETSC_USE_LOG) 9559 PetscStageLog stageLog; 9560 PetscLogEvent event; 9561 PetscLogStage stage; 9562 PetscEventPerfInfo eventInfo; 9563 PetscReal cellRate, flopRate; 9564 PetscInt cStart, cEnd, Nf, N; 9565 const char *name; 9566 PetscErrorCode ierr; 9567 #endif 9568 9569 PetscFunctionBegin; 9570 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9571 #if defined(PETSC_USE_LOG) 9572 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 9573 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9574 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9575 ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 9576 ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr); 9577 ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr); 9578 ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr); 9579 N = (cEnd - cStart)*Nf*eventInfo.count; 9580 flopRate = eventInfo.flops/eventInfo.time; 9581 cellRate = N/eventInfo.time; 9582 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); 9583 #else 9584 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 9585 #endif 9586 PetscFunctionReturn(0); 9587 } 9588