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