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