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