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