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