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