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