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