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