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