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