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