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