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