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 ierr = 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 if (dim == 2) eStart = cone[0]; 3874 else if (dim == 3) { 3875 const PetscInt *cone2; 3876 ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 3877 eStart = cone2[0]; 3878 } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering for dim %D", point, depth, dim); 3879 } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering for dim %D", point, depth, dim); 3880 if (!section) {ierr = DMGetSection(dm, §ion);CHKERRQ(ierr);} 3881 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 3882 if (dim <= 1) PetscFunctionReturn(0); 3883 for (f = 0; f < Nf; ++f) { 3884 /* An order k SEM disc has k-1 dofs on an edge */ 3885 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3886 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3887 k = k/Nc + 1; 3888 size += PetscPowInt(k+1, dim)*Nc; 3889 } 3890 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 3891 for (f = 0; f < Nf; ++f) { 3892 switch (dim) { 3893 case 2: 3894 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 3895 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3896 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3897 k = k/Nc + 1; 3898 /* The SEM order is 3899 3900 v_lb, {e_b}, v_rb, 3901 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 3902 v_lt, reverse {e_t}, v_rt 3903 */ 3904 { 3905 const PetscInt of = 0; 3906 const PetscInt oeb = of + PetscSqr(k-1); 3907 const PetscInt oer = oeb + (k-1); 3908 const PetscInt oet = oer + (k-1); 3909 const PetscInt oel = oet + (k-1); 3910 const PetscInt ovlb = oel + (k-1); 3911 const PetscInt ovrb = ovlb + 1; 3912 const PetscInt ovrt = ovrb + 1; 3913 const PetscInt ovlt = ovrt + 1; 3914 PetscInt o; 3915 3916 /* bottom */ 3917 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 3918 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3919 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 3920 /* middle */ 3921 for (i = 0; i < k-1; ++i) { 3922 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 3923 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; 3924 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 3925 } 3926 /* top */ 3927 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 3928 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3929 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 3930 foffset = offset; 3931 } 3932 break; 3933 case 3: 3934 /* The original hex closure is 3935 3936 {c, 3937 f_b, f_t, f_f, f_b, f_r, f_l, 3938 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 3939 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 3940 */ 3941 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3942 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3943 k = k/Nc + 1; 3944 /* The SEM order is 3945 Bottom Slice 3946 v_blf, {e^{(k-1)-n}_bf}, v_brf, 3947 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 3948 v_blb, {e_bb}, v_brb, 3949 3950 Middle Slice (j) 3951 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 3952 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 3953 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 3954 3955 Top Slice 3956 v_tlf, {e_tf}, v_trf, 3957 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 3958 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 3959 */ 3960 { 3961 const PetscInt oc = 0; 3962 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 3963 const PetscInt oft = ofb + PetscSqr(k-1); 3964 const PetscInt off = oft + PetscSqr(k-1); 3965 const PetscInt ofk = off + PetscSqr(k-1); 3966 const PetscInt ofr = ofk + PetscSqr(k-1); 3967 const PetscInt ofl = ofr + PetscSqr(k-1); 3968 const PetscInt oebl = ofl + PetscSqr(k-1); 3969 const PetscInt oebb = oebl + (k-1); 3970 const PetscInt oebr = oebb + (k-1); 3971 const PetscInt oebf = oebr + (k-1); 3972 const PetscInt oetf = oebf + (k-1); 3973 const PetscInt oetr = oetf + (k-1); 3974 const PetscInt oetb = oetr + (k-1); 3975 const PetscInt oetl = oetb + (k-1); 3976 const PetscInt oerf = oetl + (k-1); 3977 const PetscInt oelf = oerf + (k-1); 3978 const PetscInt oelb = oelf + (k-1); 3979 const PetscInt oerb = oelb + (k-1); 3980 const PetscInt ovblf = oerb + (k-1); 3981 const PetscInt ovblb = ovblf + 1; 3982 const PetscInt ovbrb = ovblb + 1; 3983 const PetscInt ovbrf = ovbrb + 1; 3984 const PetscInt ovtlf = ovbrf + 1; 3985 const PetscInt ovtrf = ovtlf + 1; 3986 const PetscInt ovtrb = ovtrf + 1; 3987 const PetscInt ovtlb = ovtrb + 1; 3988 PetscInt o, n; 3989 3990 /* Bottom Slice */ 3991 /* bottom */ 3992 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 3993 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3994 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 3995 /* middle */ 3996 for (i = 0; i < k-1; ++i) { 3997 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 3998 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;} 3999 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 4000 } 4001 /* top */ 4002 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 4003 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4004 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 4005 4006 /* Middle Slice */ 4007 for (j = 0; j < k-1; ++j) { 4008 /* bottom */ 4009 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 4010 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; 4011 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 4012 /* middle */ 4013 for (i = 0; i < k-1; ++i) { 4014 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 4015 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; 4016 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 4017 } 4018 /* top */ 4019 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 4020 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; 4021 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 4022 } 4023 4024 /* Top Slice */ 4025 /* bottom */ 4026 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 4027 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4028 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 4029 /* middle */ 4030 for (i = 0; i < k-1; ++i) { 4031 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 4032 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 4033 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 4034 } 4035 /* top */ 4036 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 4037 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 4038 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 4039 4040 foffset = offset; 4041 } 4042 break; 4043 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", dim); 4044 } 4045 } 4046 if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 4047 /* Check permutation */ 4048 { 4049 PetscInt *check; 4050 4051 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 4052 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]);} 4053 for (i = 0; i < size; ++i) check[perm[i]] = i; 4054 for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 4055 ierr = PetscFree(check);CHKERRQ(ierr); 4056 } 4057 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 4058 PetscFunctionReturn(0); 4059 } 4060 4061 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 4062 { 4063 PetscDS prob; 4064 PetscInt depth, Nf, h; 4065 DMLabel label; 4066 PetscErrorCode ierr; 4067 4068 PetscFunctionBeginHot; 4069 prob = dm->prob; 4070 Nf = prob->Nf; 4071 label = dm->depthLabel; 4072 *dspace = NULL; 4073 if (field < Nf) { 4074 PetscObject disc = prob->disc[field]; 4075 4076 if (disc->classid == PETSCFE_CLASSID) { 4077 PetscDualSpace dsp; 4078 4079 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 4080 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 4081 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 4082 h = depth - 1 - h; 4083 if (h) { 4084 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 4085 } else { 4086 *dspace = dsp; 4087 } 4088 } 4089 } 4090 PetscFunctionReturn(0); 4091 } 4092 4093 4094 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4095 { 4096 PetscScalar *array, *vArray; 4097 const PetscInt *cone, *coneO; 4098 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 4099 PetscErrorCode ierr; 4100 4101 PetscFunctionBeginHot; 4102 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4103 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 4104 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4105 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 4106 if (!values || !*values) { 4107 if ((point >= pStart) && (point < pEnd)) { 4108 PetscInt dof; 4109 4110 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4111 size += dof; 4112 } 4113 for (p = 0; p < numPoints; ++p) { 4114 const PetscInt cp = cone[p]; 4115 PetscInt dof; 4116 4117 if ((cp < pStart) || (cp >= pEnd)) continue; 4118 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4119 size += dof; 4120 } 4121 if (!values) { 4122 if (csize) *csize = size; 4123 PetscFunctionReturn(0); 4124 } 4125 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 4126 } else { 4127 array = *values; 4128 } 4129 size = 0; 4130 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 4131 if ((point >= pStart) && (point < pEnd)) { 4132 PetscInt dof, off, d; 4133 PetscScalar *varr; 4134 4135 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4136 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4137 varr = &vArray[off]; 4138 for (d = 0; d < dof; ++d, ++offset) { 4139 array[offset] = varr[d]; 4140 } 4141 size += dof; 4142 } 4143 for (p = 0; p < numPoints; ++p) { 4144 const PetscInt cp = cone[p]; 4145 PetscInt o = coneO[p]; 4146 PetscInt dof, off, d; 4147 PetscScalar *varr; 4148 4149 if ((cp < pStart) || (cp >= pEnd)) continue; 4150 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4151 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 4152 varr = &vArray[off]; 4153 if (o >= 0) { 4154 for (d = 0; d < dof; ++d, ++offset) { 4155 array[offset] = varr[d]; 4156 } 4157 } else { 4158 for (d = dof-1; d >= 0; --d, ++offset) { 4159 array[offset] = varr[d]; 4160 } 4161 } 4162 size += dof; 4163 } 4164 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 4165 if (!*values) { 4166 if (csize) *csize = size; 4167 *values = array; 4168 } else { 4169 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 4170 *csize = size; 4171 } 4172 PetscFunctionReturn(0); 4173 } 4174 4175 static PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 4176 { 4177 const PetscInt *cla; 4178 PetscInt np, *pts = NULL; 4179 PetscErrorCode ierr; 4180 4181 PetscFunctionBeginHot; 4182 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 4183 if (!*clPoints) { 4184 PetscInt pStart, pEnd, p, q; 4185 4186 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4187 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 4188 /* Compress out points not in the section */ 4189 for (p = 0, q = 0; p < np; p++) { 4190 PetscInt r = pts[2*p]; 4191 if ((r >= pStart) && (r < pEnd)) { 4192 pts[q*2] = r; 4193 pts[q*2+1] = pts[2*p+1]; 4194 ++q; 4195 } 4196 } 4197 np = q; 4198 cla = NULL; 4199 } else { 4200 PetscInt dof, off; 4201 4202 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 4203 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 4204 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 4205 np = dof/2; 4206 pts = (PetscInt *) &cla[off]; 4207 } 4208 *numPoints = np; 4209 *points = pts; 4210 *clp = cla; 4211 4212 PetscFunctionReturn(0); 4213 } 4214 4215 static PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 4216 { 4217 PetscErrorCode ierr; 4218 4219 PetscFunctionBeginHot; 4220 if (!*clPoints) { 4221 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 4222 } else { 4223 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 4224 } 4225 *numPoints = 0; 4226 *points = NULL; 4227 *clSec = NULL; 4228 *clPoints = NULL; 4229 *clp = NULL; 4230 PetscFunctionReturn(0); 4231 } 4232 4233 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[]) 4234 { 4235 PetscInt offset = 0, p; 4236 const PetscInt **perms = NULL; 4237 const PetscScalar **flips = NULL; 4238 PetscErrorCode ierr; 4239 4240 PetscFunctionBeginHot; 4241 *size = 0; 4242 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4243 for (p = 0; p < numPoints; p++) { 4244 const PetscInt point = points[2*p]; 4245 const PetscInt *perm = perms ? perms[p] : NULL; 4246 const PetscScalar *flip = flips ? flips[p] : NULL; 4247 PetscInt dof, off, d; 4248 const PetscScalar *varr; 4249 4250 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4251 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4252 varr = &vArray[off]; 4253 if (clperm) { 4254 if (perm) { 4255 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 4256 } else { 4257 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 4258 } 4259 if (flip) { 4260 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 4261 } 4262 } else { 4263 if (perm) { 4264 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 4265 } else { 4266 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 4267 } 4268 if (flip) { 4269 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 4270 } 4271 } 4272 offset += dof; 4273 } 4274 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4275 *size = offset; 4276 PetscFunctionReturn(0); 4277 } 4278 4279 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[]) 4280 { 4281 PetscInt offset = 0, f; 4282 PetscErrorCode ierr; 4283 4284 PetscFunctionBeginHot; 4285 *size = 0; 4286 for (f = 0; f < numFields; ++f) { 4287 PetscInt p; 4288 const PetscInt **perms = NULL; 4289 const PetscScalar **flips = NULL; 4290 4291 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4292 for (p = 0; p < numPoints; p++) { 4293 const PetscInt point = points[2*p]; 4294 PetscInt fdof, foff, b; 4295 const PetscScalar *varr; 4296 const PetscInt *perm = perms ? perms[p] : NULL; 4297 const PetscScalar *flip = flips ? flips[p] : NULL; 4298 4299 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4300 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4301 varr = &vArray[foff]; 4302 if (clperm) { 4303 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 4304 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 4305 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 4306 } else { 4307 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 4308 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 4309 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 4310 } 4311 offset += fdof; 4312 } 4313 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4314 } 4315 *size = offset; 4316 PetscFunctionReturn(0); 4317 } 4318 4319 /*@C 4320 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 4321 4322 Not collective 4323 4324 Input Parameters: 4325 + dm - The DM 4326 . section - The section describing the layout in v, or NULL to use the default section 4327 . v - The local vector 4328 . point - The point in the DM 4329 . csize - The size of the input values array, or NULL 4330 - values - An array to use for the values, or NULL to have it allocated automatically 4331 4332 Output Parameters: 4333 + csize - The number of values in the closure 4334 - values - The array of values. If the user provided NULL, it is a borrowed array and should not be freed 4335 4336 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 4337 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 4338 $ assembly function, and a user may already have allocated storage for this operation. 4339 $ 4340 $ A typical use could be 4341 $ 4342 $ values = NULL; 4343 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4344 $ for (cl = 0; cl < clSize; ++cl) { 4345 $ <Compute on closure> 4346 $ } 4347 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4348 $ 4349 $ or 4350 $ 4351 $ PetscMalloc1(clMaxSize, &values); 4352 $ for (p = pStart; p < pEnd; ++p) { 4353 $ clSize = clMaxSize; 4354 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4355 $ for (cl = 0; cl < clSize; ++cl) { 4356 $ <Compute on closure> 4357 $ } 4358 $ } 4359 $ PetscFree(values); 4360 4361 Fortran Notes: 4362 Since it returns an array, this routine is only available in Fortran 90, and you must 4363 include petsc.h90 in your code. 4364 4365 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4366 4367 Level: intermediate 4368 4369 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4370 @*/ 4371 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4372 { 4373 PetscSection clSection; 4374 IS clPoints; 4375 PetscScalar *array; 4376 const PetscScalar *vArray; 4377 PetscInt *points = NULL; 4378 const PetscInt *clp, *perm; 4379 PetscInt depth, numFields, numPoints, size; 4380 PetscErrorCode ierr; 4381 4382 PetscFunctionBeginHot; 4383 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4384 if (!section) {ierr = DMGetSection(dm, §ion);CHKERRQ(ierr);} 4385 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4386 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4387 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4388 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4389 if (depth == 1 && numFields < 2) { 4390 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 4391 PetscFunctionReturn(0); 4392 } 4393 /* Get points */ 4394 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4395 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &perm);CHKERRQ(ierr); 4396 /* Get array */ 4397 if (!values || !*values) { 4398 PetscInt asize = 0, dof, p; 4399 4400 for (p = 0; p < numPoints*2; p += 2) { 4401 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4402 asize += dof; 4403 } 4404 if (!values) { 4405 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4406 if (csize) *csize = asize; 4407 PetscFunctionReturn(0); 4408 } 4409 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 4410 } else { 4411 array = *values; 4412 } 4413 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 4414 /* Get values */ 4415 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 4416 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, array);CHKERRQ(ierr);} 4417 /* Cleanup points */ 4418 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4419 /* Cleanup array */ 4420 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 4421 if (!*values) { 4422 if (csize) *csize = size; 4423 *values = array; 4424 } else { 4425 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 4426 *csize = size; 4427 } 4428 PetscFunctionReturn(0); 4429 } 4430 4431 /*@C 4432 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 4433 4434 Not collective 4435 4436 Input Parameters: 4437 + dm - The DM 4438 . section - The section describing the layout in v, or NULL to use the default section 4439 . v - The local vector 4440 . point - The point in the DM 4441 . csize - The number of values in the closure, or NULL 4442 - values - The array of values, which is a borrowed array and should not be freed 4443 4444 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 4445 4446 Fortran Notes: 4447 Since it returns an array, this routine is only available in Fortran 90, and you must 4448 include petsc.h90 in your code. 4449 4450 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4451 4452 Level: intermediate 4453 4454 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4455 @*/ 4456 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4457 { 4458 PetscInt size = 0; 4459 PetscErrorCode ierr; 4460 4461 PetscFunctionBegin; 4462 /* Should work without recalculating size */ 4463 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 4464 *values = NULL; 4465 PetscFunctionReturn(0); 4466 } 4467 4468 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 4469 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 4470 4471 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[]) 4472 { 4473 PetscInt cdof; /* The number of constraints on this point */ 4474 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4475 PetscScalar *a; 4476 PetscInt off, cind = 0, k; 4477 PetscErrorCode ierr; 4478 4479 PetscFunctionBegin; 4480 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4481 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4482 a = &array[off]; 4483 if (!cdof || setBC) { 4484 if (clperm) { 4485 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 4486 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 4487 } else { 4488 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 4489 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 4490 } 4491 } else { 4492 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4493 if (clperm) { 4494 if (perm) {for (k = 0; k < dof; ++k) { 4495 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4496 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 4497 } 4498 } else { 4499 for (k = 0; k < dof; ++k) { 4500 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4501 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 4502 } 4503 } 4504 } else { 4505 if (perm) { 4506 for (k = 0; k < dof; ++k) { 4507 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4508 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 4509 } 4510 } else { 4511 for (k = 0; k < dof; ++k) { 4512 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4513 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 4514 } 4515 } 4516 } 4517 } 4518 PetscFunctionReturn(0); 4519 } 4520 4521 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[]) 4522 { 4523 PetscInt cdof; /* The number of constraints on this point */ 4524 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4525 PetscScalar *a; 4526 PetscInt off, cind = 0, k; 4527 PetscErrorCode ierr; 4528 4529 PetscFunctionBegin; 4530 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4531 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4532 a = &array[off]; 4533 if (cdof) { 4534 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4535 if (clperm) { 4536 if (perm) { 4537 for (k = 0; k < dof; ++k) { 4538 if ((cind < cdof) && (k == cdofs[cind])) { 4539 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 4540 cind++; 4541 } 4542 } 4543 } else { 4544 for (k = 0; k < dof; ++k) { 4545 if ((cind < cdof) && (k == cdofs[cind])) { 4546 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 4547 cind++; 4548 } 4549 } 4550 } 4551 } else { 4552 if (perm) { 4553 for (k = 0; k < dof; ++k) { 4554 if ((cind < cdof) && (k == cdofs[cind])) { 4555 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 4556 cind++; 4557 } 4558 } 4559 } else { 4560 for (k = 0; k < dof; ++k) { 4561 if ((cind < cdof) && (k == cdofs[cind])) { 4562 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 4563 cind++; 4564 } 4565 } 4566 } 4567 } 4568 } 4569 PetscFunctionReturn(0); 4570 } 4571 4572 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[]) 4573 { 4574 PetscScalar *a; 4575 PetscInt fdof, foff, fcdof, foffset = *offset; 4576 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4577 PetscInt cind = 0, b; 4578 PetscErrorCode ierr; 4579 4580 PetscFunctionBegin; 4581 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4582 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 4583 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4584 a = &array[foff]; 4585 if (!fcdof || setBC) { 4586 if (clperm) { 4587 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 4588 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 4589 } else { 4590 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 4591 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 4592 } 4593 } else { 4594 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4595 if (clperm) { 4596 if (perm) { 4597 for (b = 0; b < fdof; b++) { 4598 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4599 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 4600 } 4601 } else { 4602 for (b = 0; b < fdof; b++) { 4603 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4604 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 4605 } 4606 } 4607 } else { 4608 if (perm) { 4609 for (b = 0; b < fdof; b++) { 4610 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4611 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 4612 } 4613 } else { 4614 for (b = 0; b < fdof; b++) { 4615 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4616 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 4617 } 4618 } 4619 } 4620 } 4621 *offset += fdof; 4622 PetscFunctionReturn(0); 4623 } 4624 4625 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[]) 4626 { 4627 PetscScalar *a; 4628 PetscInt fdof, foff, fcdof, foffset = *offset; 4629 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4630 PetscInt cind = 0, ncind = 0, b; 4631 PetscBool ncSet, fcSet; 4632 PetscErrorCode ierr; 4633 4634 PetscFunctionBegin; 4635 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4636 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 4637 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4638 a = &array[foff]; 4639 if (fcdof) { 4640 /* We just override fcdof and fcdofs with Ncc and comps */ 4641 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4642 if (clperm) { 4643 if (perm) { 4644 if (comps) { 4645 for (b = 0; b < fdof; b++) { 4646 ncSet = fcSet = PETSC_FALSE; 4647 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4648 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4649 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 4650 } 4651 } else { 4652 for (b = 0; b < fdof; b++) { 4653 if ((cind < fcdof) && (b == fcdofs[cind])) { 4654 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 4655 ++cind; 4656 } 4657 } 4658 } 4659 } else { 4660 if (comps) { 4661 for (b = 0; b < fdof; b++) { 4662 ncSet = fcSet = PETSC_FALSE; 4663 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4664 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4665 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 4666 } 4667 } else { 4668 for (b = 0; b < fdof; b++) { 4669 if ((cind < fcdof) && (b == fcdofs[cind])) { 4670 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 4671 ++cind; 4672 } 4673 } 4674 } 4675 } 4676 } else { 4677 if (perm) { 4678 if (comps) { 4679 for (b = 0; b < fdof; b++) { 4680 ncSet = fcSet = PETSC_FALSE; 4681 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4682 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4683 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 4684 } 4685 } else { 4686 for (b = 0; b < fdof; b++) { 4687 if ((cind < fcdof) && (b == fcdofs[cind])) { 4688 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 4689 ++cind; 4690 } 4691 } 4692 } 4693 } else { 4694 if (comps) { 4695 for (b = 0; b < fdof; b++) { 4696 ncSet = fcSet = PETSC_FALSE; 4697 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4698 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4699 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 4700 } 4701 } else { 4702 for (b = 0; b < fdof; b++) { 4703 if ((cind < fcdof) && (b == fcdofs[cind])) { 4704 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 4705 ++cind; 4706 } 4707 } 4708 } 4709 } 4710 } 4711 } 4712 *offset += fdof; 4713 PetscFunctionReturn(0); 4714 } 4715 4716 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4717 { 4718 PetscScalar *array; 4719 const PetscInt *cone, *coneO; 4720 PetscInt pStart, pEnd, p, numPoints, off, dof; 4721 PetscErrorCode ierr; 4722 4723 PetscFunctionBeginHot; 4724 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4725 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 4726 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4727 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 4728 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4729 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 4730 const PetscInt cp = !p ? point : cone[p-1]; 4731 const PetscInt o = !p ? 0 : coneO[p-1]; 4732 4733 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 4734 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4735 /* ADD_VALUES */ 4736 { 4737 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4738 PetscScalar *a; 4739 PetscInt cdof, coff, cind = 0, k; 4740 4741 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 4742 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 4743 a = &array[coff]; 4744 if (!cdof) { 4745 if (o >= 0) { 4746 for (k = 0; k < dof; ++k) { 4747 a[k] += values[off+k]; 4748 } 4749 } else { 4750 for (k = 0; k < dof; ++k) { 4751 a[k] += values[off+dof-k-1]; 4752 } 4753 } 4754 } else { 4755 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 4756 if (o >= 0) { 4757 for (k = 0; k < dof; ++k) { 4758 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4759 a[k] += values[off+k]; 4760 } 4761 } else { 4762 for (k = 0; k < dof; ++k) { 4763 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4764 a[k] += values[off+dof-k-1]; 4765 } 4766 } 4767 } 4768 } 4769 } 4770 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4771 PetscFunctionReturn(0); 4772 } 4773 4774 /*@C 4775 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 4776 4777 Not collective 4778 4779 Input Parameters: 4780 + dm - The DM 4781 . section - The section describing the layout in v, or NULL to use the default section 4782 . v - The local vector 4783 . point - The point in the DM 4784 . values - The array of values 4785 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 4786 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 4787 4788 Fortran Notes: 4789 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4790 4791 Level: intermediate 4792 4793 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 4794 @*/ 4795 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4796 { 4797 PetscSection clSection; 4798 IS clPoints; 4799 PetscScalar *array; 4800 PetscInt *points = NULL; 4801 const PetscInt *clp, *clperm; 4802 PetscInt depth, numFields, numPoints, p; 4803 PetscErrorCode ierr; 4804 4805 PetscFunctionBeginHot; 4806 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4807 if (!section) {ierr = DMGetSection(dm, §ion);CHKERRQ(ierr);} 4808 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4809 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4810 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4811 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4812 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 4813 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 4814 PetscFunctionReturn(0); 4815 } 4816 /* Get points */ 4817 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 4818 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4819 /* Get array */ 4820 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4821 /* Get values */ 4822 if (numFields > 0) { 4823 PetscInt offset = 0, f; 4824 for (f = 0; f < numFields; ++f) { 4825 const PetscInt **perms = NULL; 4826 const PetscScalar **flips = NULL; 4827 4828 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4829 switch (mode) { 4830 case INSERT_VALUES: 4831 for (p = 0; p < numPoints; p++) { 4832 const PetscInt point = points[2*p]; 4833 const PetscInt *perm = perms ? perms[p] : NULL; 4834 const PetscScalar *flip = flips ? flips[p] : NULL; 4835 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 4836 } break; 4837 case INSERT_ALL_VALUES: 4838 for (p = 0; p < numPoints; p++) { 4839 const PetscInt point = points[2*p]; 4840 const PetscInt *perm = perms ? perms[p] : NULL; 4841 const PetscScalar *flip = flips ? flips[p] : NULL; 4842 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 4843 } break; 4844 case INSERT_BC_VALUES: 4845 for (p = 0; p < numPoints; p++) { 4846 const PetscInt point = points[2*p]; 4847 const PetscInt *perm = perms ? perms[p] : NULL; 4848 const PetscScalar *flip = flips ? flips[p] : NULL; 4849 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 4850 } break; 4851 case ADD_VALUES: 4852 for (p = 0; p < numPoints; p++) { 4853 const PetscInt point = points[2*p]; 4854 const PetscInt *perm = perms ? perms[p] : NULL; 4855 const PetscScalar *flip = flips ? flips[p] : NULL; 4856 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 4857 } break; 4858 case ADD_ALL_VALUES: 4859 for (p = 0; p < numPoints; p++) { 4860 const PetscInt point = points[2*p]; 4861 const PetscInt *perm = perms ? perms[p] : NULL; 4862 const PetscScalar *flip = flips ? flips[p] : NULL; 4863 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 4864 } break; 4865 case ADD_BC_VALUES: 4866 for (p = 0; p < numPoints; p++) { 4867 const PetscInt point = points[2*p]; 4868 const PetscInt *perm = perms ? perms[p] : NULL; 4869 const PetscScalar *flip = flips ? flips[p] : NULL; 4870 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 4871 } break; 4872 default: 4873 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4874 } 4875 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4876 } 4877 } else { 4878 PetscInt dof, off; 4879 const PetscInt **perms = NULL; 4880 const PetscScalar **flips = NULL; 4881 4882 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4883 switch (mode) { 4884 case INSERT_VALUES: 4885 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4886 const PetscInt point = points[2*p]; 4887 const PetscInt *perm = perms ? perms[p] : NULL; 4888 const PetscScalar *flip = flips ? flips[p] : NULL; 4889 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4890 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 4891 } break; 4892 case INSERT_ALL_VALUES: 4893 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4894 const PetscInt point = points[2*p]; 4895 const PetscInt *perm = perms ? perms[p] : NULL; 4896 const PetscScalar *flip = flips ? flips[p] : NULL; 4897 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4898 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 4899 } break; 4900 case INSERT_BC_VALUES: 4901 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4902 const PetscInt point = points[2*p]; 4903 const PetscInt *perm = perms ? perms[p] : NULL; 4904 const PetscScalar *flip = flips ? flips[p] : NULL; 4905 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4906 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 4907 } break; 4908 case ADD_VALUES: 4909 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4910 const PetscInt point = points[2*p]; 4911 const PetscInt *perm = perms ? perms[p] : NULL; 4912 const PetscScalar *flip = flips ? flips[p] : NULL; 4913 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4914 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 4915 } break; 4916 case ADD_ALL_VALUES: 4917 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4918 const PetscInt point = points[2*p]; 4919 const PetscInt *perm = perms ? perms[p] : NULL; 4920 const PetscScalar *flip = flips ? flips[p] : NULL; 4921 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4922 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 4923 } break; 4924 case ADD_BC_VALUES: 4925 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4926 const PetscInt point = points[2*p]; 4927 const PetscInt *perm = perms ? perms[p] : NULL; 4928 const PetscScalar *flip = flips ? flips[p] : NULL; 4929 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4930 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 4931 } break; 4932 default: 4933 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4934 } 4935 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4936 } 4937 /* Cleanup points */ 4938 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4939 /* Cleanup array */ 4940 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4941 PetscFunctionReturn(0); 4942 } 4943 4944 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, PetscInt Ncc, const PetscInt comps[], const PetscScalar values[], InsertMode mode) 4945 { 4946 PetscSection clSection; 4947 IS clPoints; 4948 PetscScalar *array; 4949 PetscInt *points = NULL; 4950 const PetscInt *clp, *clperm; 4951 PetscInt numFields, numPoints, p; 4952 PetscInt offset = 0, f; 4953 PetscErrorCode ierr; 4954 4955 PetscFunctionBeginHot; 4956 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4957 if (!section) {ierr = DMGetSection(dm, §ion);CHKERRQ(ierr);} 4958 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4959 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4960 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4961 /* Get points */ 4962 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 4963 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4964 /* Get array */ 4965 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4966 /* Get values */ 4967 for (f = 0; f < numFields; ++f) { 4968 const PetscInt **perms = NULL; 4969 const PetscScalar **flips = NULL; 4970 4971 if (!fieldActive[f]) { 4972 for (p = 0; p < numPoints*2; p += 2) { 4973 PetscInt fdof; 4974 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4975 offset += fdof; 4976 } 4977 continue; 4978 } 4979 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4980 switch (mode) { 4981 case INSERT_VALUES: 4982 for (p = 0; p < numPoints; p++) { 4983 const PetscInt point = points[2*p]; 4984 const PetscInt *perm = perms ? perms[p] : NULL; 4985 const PetscScalar *flip = flips ? flips[p] : NULL; 4986 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 4987 } break; 4988 case INSERT_ALL_VALUES: 4989 for (p = 0; p < numPoints; p++) { 4990 const PetscInt point = points[2*p]; 4991 const PetscInt *perm = perms ? perms[p] : NULL; 4992 const PetscScalar *flip = flips ? flips[p] : NULL; 4993 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 4994 } break; 4995 case INSERT_BC_VALUES: 4996 for (p = 0; p < numPoints; p++) { 4997 const PetscInt point = points[2*p]; 4998 const PetscInt *perm = perms ? perms[p] : NULL; 4999 const PetscScalar *flip = flips ? flips[p] : NULL; 5000 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, clperm, values, &offset, array); 5001 } break; 5002 case ADD_VALUES: 5003 for (p = 0; p < numPoints; p++) { 5004 const PetscInt point = points[2*p]; 5005 const PetscInt *perm = perms ? perms[p] : NULL; 5006 const PetscScalar *flip = flips ? flips[p] : NULL; 5007 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 5008 } break; 5009 case ADD_ALL_VALUES: 5010 for (p = 0; p < numPoints; p++) { 5011 const PetscInt point = points[2*p]; 5012 const PetscInt *perm = perms ? perms[p] : NULL; 5013 const PetscScalar *flip = flips ? flips[p] : NULL; 5014 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 5015 } break; 5016 default: 5017 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 5018 } 5019 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5020 } 5021 /* Cleanup points */ 5022 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5023 /* Cleanup array */ 5024 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 5025 PetscFunctionReturn(0); 5026 } 5027 5028 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 5029 { 5030 PetscMPIInt rank; 5031 PetscInt i, j; 5032 PetscErrorCode ierr; 5033 5034 PetscFunctionBegin; 5035 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 5036 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 5037 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 5038 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 5039 numCIndices = numCIndices ? numCIndices : numRIndices; 5040 for (i = 0; i < numRIndices; i++) { 5041 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 5042 for (j = 0; j < numCIndices; j++) { 5043 #if defined(PETSC_USE_COMPLEX) 5044 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 5045 #else 5046 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 5047 #endif 5048 } 5049 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 5050 } 5051 PetscFunctionReturn(0); 5052 } 5053 5054 /* . off - The global offset of this point */ 5055 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], PetscInt indices[]) 5056 { 5057 PetscInt dof; /* The number of unknowns on this point */ 5058 PetscInt cdof; /* The number of constraints on this point */ 5059 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5060 PetscInt cind = 0, k; 5061 PetscErrorCode ierr; 5062 5063 PetscFunctionBegin; 5064 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5065 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5066 if (!cdof || setBC) { 5067 if (perm) { 5068 for (k = 0; k < dof; k++) indices[*loff+perm[k]] = off + k; 5069 } else { 5070 for (k = 0; k < dof; k++) indices[*loff+k] = off + k; 5071 } 5072 } else { 5073 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 5074 if (perm) { 5075 for (k = 0; k < dof; ++k) { 5076 if ((cind < cdof) && (k == cdofs[cind])) { 5077 /* Insert check for returning constrained indices */ 5078 indices[*loff+perm[k]] = -(off+k+1); 5079 ++cind; 5080 } else { 5081 indices[*loff+perm[k]] = off+k-cind; 5082 } 5083 } 5084 } else { 5085 for (k = 0; k < dof; ++k) { 5086 if ((cind < cdof) && (k == cdofs[cind])) { 5087 /* Insert check for returning constrained indices */ 5088 indices[*loff+k] = -(off+k+1); 5089 ++cind; 5090 } else { 5091 indices[*loff+k] = off+k-cind; 5092 } 5093 } 5094 } 5095 } 5096 *loff += dof; 5097 PetscFunctionReturn(0); 5098 } 5099 5100 /* 5101 This version only believes the point offset from the globalSection 5102 5103 . off - The global offset of this point 5104 */ 5105 PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, PetscInt indices[]) 5106 { 5107 PetscInt numFields, foff, f; 5108 PetscErrorCode ierr; 5109 5110 PetscFunctionBegin; 5111 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5112 for (f = 0, foff = 0; f < numFields; ++f) { 5113 PetscInt fdof, cfdof; 5114 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5115 PetscInt cind = 0, b; 5116 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 5117 5118 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5119 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 5120 if (!cfdof || setBC) { 5121 if (perm) {for (b = 0; b < fdof; b++) {indices[foffs[f]+perm[b]] = off+foff+b;}} 5122 else {for (b = 0; b < fdof; b++) {indices[foffs[f]+ b ] = off+foff+b;}} 5123 } else { 5124 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5125 if (perm) { 5126 for (b = 0; b < fdof; b++) { 5127 if ((cind < cfdof) && (b == fcdofs[cind])) { 5128 indices[foffs[f]+perm[b]] = -(off+foff+b+1); 5129 ++cind; 5130 } else { 5131 indices[foffs[f]+perm[b]] = off+foff+b-cind; 5132 } 5133 } 5134 } else { 5135 for (b = 0; b < fdof; b++) { 5136 if ((cind < cfdof) && (b == fcdofs[cind])) { 5137 indices[foffs[f]+b] = -(off+foff+b+1); 5138 ++cind; 5139 } else { 5140 indices[foffs[f]+b] = off+foff+b-cind; 5141 } 5142 } 5143 } 5144 } 5145 foff += (setBC ? fdof : (fdof - cfdof)); 5146 foffs[f] += fdof; 5147 } 5148 PetscFunctionReturn(0); 5149 } 5150 5151 /* 5152 This version believes the globalSection offsets for each field, rather than just the point offset 5153 5154 . foffs - The offset into 'indices' for each field, since it is segregated by field 5155 */ 5156 PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, PetscInt indices[]) 5157 { 5158 PetscInt numFields, foff, f; 5159 PetscErrorCode ierr; 5160 5161 PetscFunctionBegin; 5162 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5163 for (f = 0; f < numFields; ++f) { 5164 PetscInt fdof, cfdof; 5165 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 5166 PetscInt cind = 0, b; 5167 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 5168 5169 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5170 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 5171 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 5172 if (!cfdof || setBC) { 5173 if (perm) {for (b = 0; b < fdof; b++) {indices[foffs[f]+perm[b]] = foff+b;}} 5174 else {for (b = 0; b < fdof; b++) {indices[foffs[f]+ b ] = foff+b;}} 5175 } else { 5176 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 5177 if (perm) { 5178 for (b = 0; b < fdof; b++) { 5179 if ((cind < cfdof) && (b == fcdofs[cind])) { 5180 indices[foffs[f]+perm[b]] = -(foff+b+1); 5181 ++cind; 5182 } else { 5183 indices[foffs[f]+perm[b]] = foff+b-cind; 5184 } 5185 } 5186 } else { 5187 for (b = 0; b < fdof; b++) { 5188 if ((cind < cfdof) && (b == fcdofs[cind])) { 5189 indices[foffs[f]+b] = -(foff+b+1); 5190 ++cind; 5191 } else { 5192 indices[foffs[f]+b] = foff+b-cind; 5193 } 5194 } 5195 } 5196 } 5197 foffs[f] += fdof; 5198 } 5199 PetscFunctionReturn(0); 5200 } 5201 5202 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) 5203 { 5204 Mat cMat; 5205 PetscSection aSec, cSec; 5206 IS aIS; 5207 PetscInt aStart = -1, aEnd = -1; 5208 const PetscInt *anchors; 5209 PetscInt numFields, f, p, q, newP = 0; 5210 PetscInt newNumPoints = 0, newNumIndices = 0; 5211 PetscInt *newPoints, *indices, *newIndices; 5212 PetscInt maxAnchor, maxDof; 5213 PetscInt newOffsets[32]; 5214 PetscInt *pointMatOffsets[32]; 5215 PetscInt *newPointOffsets[32]; 5216 PetscScalar *pointMat[32]; 5217 PetscScalar *newValues=NULL,*tmpValues; 5218 PetscBool anyConstrained = PETSC_FALSE; 5219 PetscErrorCode ierr; 5220 5221 PetscFunctionBegin; 5222 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5223 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5224 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5225 5226 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 5227 /* if there are point-to-point constraints */ 5228 if (aSec) { 5229 ierr = PetscMemzero(newOffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5230 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 5231 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 5232 /* figure out how many points are going to be in the new element matrix 5233 * (we allow double counting, because it's all just going to be summed 5234 * into the global matrix anyway) */ 5235 for (p = 0; p < 2*numPoints; p+=2) { 5236 PetscInt b = points[p]; 5237 PetscInt bDof = 0, bSecDof; 5238 5239 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5240 if (!bSecDof) { 5241 continue; 5242 } 5243 if (b >= aStart && b < aEnd) { 5244 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 5245 } 5246 if (bDof) { 5247 /* this point is constrained */ 5248 /* it is going to be replaced by its anchors */ 5249 PetscInt bOff, q; 5250 5251 anyConstrained = PETSC_TRUE; 5252 newNumPoints += bDof; 5253 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 5254 for (q = 0; q < bDof; q++) { 5255 PetscInt a = anchors[bOff + q]; 5256 PetscInt aDof; 5257 5258 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 5259 newNumIndices += aDof; 5260 for (f = 0; f < numFields; ++f) { 5261 PetscInt fDof; 5262 5263 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 5264 newOffsets[f+1] += fDof; 5265 } 5266 } 5267 } 5268 else { 5269 /* this point is not constrained */ 5270 newNumPoints++; 5271 newNumIndices += bSecDof; 5272 for (f = 0; f < numFields; ++f) { 5273 PetscInt fDof; 5274 5275 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5276 newOffsets[f+1] += fDof; 5277 } 5278 } 5279 } 5280 } 5281 if (!anyConstrained) { 5282 if (outNumPoints) *outNumPoints = 0; 5283 if (outNumIndices) *outNumIndices = 0; 5284 if (outPoints) *outPoints = NULL; 5285 if (outValues) *outValues = NULL; 5286 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 5287 PetscFunctionReturn(0); 5288 } 5289 5290 if (outNumPoints) *outNumPoints = newNumPoints; 5291 if (outNumIndices) *outNumIndices = newNumIndices; 5292 5293 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 5294 5295 if (!outPoints && !outValues) { 5296 if (offsets) { 5297 for (f = 0; f <= numFields; f++) { 5298 offsets[f] = newOffsets[f]; 5299 } 5300 } 5301 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 5302 PetscFunctionReturn(0); 5303 } 5304 5305 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 5306 5307 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 5308 5309 /* workspaces */ 5310 if (numFields) { 5311 for (f = 0; f < numFields; f++) { 5312 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 5313 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 5314 } 5315 } 5316 else { 5317 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 5318 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 5319 } 5320 5321 /* get workspaces for the point-to-point matrices */ 5322 if (numFields) { 5323 PetscInt totalOffset, totalMatOffset; 5324 5325 for (p = 0; p < numPoints; p++) { 5326 PetscInt b = points[2*p]; 5327 PetscInt bDof = 0, bSecDof; 5328 5329 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5330 if (!bSecDof) { 5331 for (f = 0; f < numFields; f++) { 5332 newPointOffsets[f][p + 1] = 0; 5333 pointMatOffsets[f][p + 1] = 0; 5334 } 5335 continue; 5336 } 5337 if (b >= aStart && b < aEnd) { 5338 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5339 } 5340 if (bDof) { 5341 for (f = 0; f < numFields; f++) { 5342 PetscInt fDof, q, bOff, allFDof = 0; 5343 5344 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5345 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5346 for (q = 0; q < bDof; q++) { 5347 PetscInt a = anchors[bOff + q]; 5348 PetscInt aFDof; 5349 5350 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 5351 allFDof += aFDof; 5352 } 5353 newPointOffsets[f][p+1] = allFDof; 5354 pointMatOffsets[f][p+1] = fDof * allFDof; 5355 } 5356 } 5357 else { 5358 for (f = 0; f < numFields; f++) { 5359 PetscInt fDof; 5360 5361 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5362 newPointOffsets[f][p+1] = fDof; 5363 pointMatOffsets[f][p+1] = 0; 5364 } 5365 } 5366 } 5367 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 5368 newPointOffsets[f][0] = totalOffset; 5369 pointMatOffsets[f][0] = totalMatOffset; 5370 for (p = 0; p < numPoints; p++) { 5371 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 5372 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 5373 } 5374 totalOffset = newPointOffsets[f][numPoints]; 5375 totalMatOffset = pointMatOffsets[f][numPoints]; 5376 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 5377 } 5378 } 5379 else { 5380 for (p = 0; p < numPoints; p++) { 5381 PetscInt b = points[2*p]; 5382 PetscInt bDof = 0, bSecDof; 5383 5384 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5385 if (!bSecDof) { 5386 newPointOffsets[0][p + 1] = 0; 5387 pointMatOffsets[0][p + 1] = 0; 5388 continue; 5389 } 5390 if (b >= aStart && b < aEnd) { 5391 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5392 } 5393 if (bDof) { 5394 PetscInt bOff, q, allDof = 0; 5395 5396 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5397 for (q = 0; q < bDof; q++) { 5398 PetscInt a = anchors[bOff + q], aDof; 5399 5400 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 5401 allDof += aDof; 5402 } 5403 newPointOffsets[0][p+1] = allDof; 5404 pointMatOffsets[0][p+1] = bSecDof * allDof; 5405 } 5406 else { 5407 newPointOffsets[0][p+1] = bSecDof; 5408 pointMatOffsets[0][p+1] = 0; 5409 } 5410 } 5411 newPointOffsets[0][0] = 0; 5412 pointMatOffsets[0][0] = 0; 5413 for (p = 0; p < numPoints; p++) { 5414 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 5415 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 5416 } 5417 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 5418 } 5419 5420 /* output arrays */ 5421 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5422 5423 /* get the point-to-point matrices; construct newPoints */ 5424 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 5425 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 5426 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 5427 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 5428 if (numFields) { 5429 for (p = 0, newP = 0; p < numPoints; p++) { 5430 PetscInt b = points[2*p]; 5431 PetscInt o = points[2*p+1]; 5432 PetscInt bDof = 0, bSecDof; 5433 5434 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 5435 if (!bSecDof) { 5436 continue; 5437 } 5438 if (b >= aStart && b < aEnd) { 5439 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5440 } 5441 if (bDof) { 5442 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 5443 5444 fStart[0] = 0; 5445 fEnd[0] = 0; 5446 for (f = 0; f < numFields; f++) { 5447 PetscInt fDof; 5448 5449 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 5450 fStart[f+1] = fStart[f] + fDof; 5451 fEnd[f+1] = fStart[f+1]; 5452 } 5453 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 5454 ierr = DMPlexGetIndicesPointFields_Internal(cSec, b, bOff, fEnd, PETSC_TRUE, perms, p, indices);CHKERRQ(ierr); 5455 5456 fAnchorStart[0] = 0; 5457 fAnchorEnd[0] = 0; 5458 for (f = 0; f < numFields; f++) { 5459 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 5460 5461 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 5462 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 5463 } 5464 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5465 for (q = 0; q < bDof; q++) { 5466 PetscInt a = anchors[bOff + q], aOff; 5467 5468 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 5469 newPoints[2*(newP + q)] = a; 5470 newPoints[2*(newP + q) + 1] = 0; 5471 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 5472 ierr = DMPlexGetIndicesPointFields_Internal(section, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, newIndices);CHKERRQ(ierr); 5473 } 5474 newP += bDof; 5475 5476 if (outValues) { 5477 /* get the point-to-point submatrix */ 5478 for (f = 0; f < numFields; f++) { 5479 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 5480 } 5481 } 5482 } 5483 else { 5484 newPoints[2 * newP] = b; 5485 newPoints[2 * newP + 1] = o; 5486 newP++; 5487 } 5488 } 5489 } else { 5490 for (p = 0; p < numPoints; p++) { 5491 PetscInt b = points[2*p]; 5492 PetscInt o = points[2*p+1]; 5493 PetscInt bDof = 0, bSecDof; 5494 5495 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 5496 if (!bSecDof) { 5497 continue; 5498 } 5499 if (b >= aStart && b < aEnd) { 5500 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5501 } 5502 if (bDof) { 5503 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 5504 5505 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 5506 ierr = DMPlexGetIndicesPoint_Internal(cSec, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, indices);CHKERRQ(ierr); 5507 5508 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 5509 for (q = 0; q < bDof; q++) { 5510 PetscInt a = anchors[bOff + q], aOff; 5511 5512 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 5513 5514 newPoints[2*(newP + q)] = a; 5515 newPoints[2*(newP + q) + 1] = 0; 5516 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 5517 ierr = DMPlexGetIndicesPoint_Internal(section, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, newIndices);CHKERRQ(ierr); 5518 } 5519 newP += bDof; 5520 5521 /* get the point-to-point submatrix */ 5522 if (outValues) { 5523 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 5524 } 5525 } 5526 else { 5527 newPoints[2 * newP] = b; 5528 newPoints[2 * newP + 1] = o; 5529 newP++; 5530 } 5531 } 5532 } 5533 5534 if (outValues) { 5535 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 5536 ierr = PetscMemzero(tmpValues,newNumIndices*numIndices*sizeof(*tmpValues));CHKERRQ(ierr); 5537 /* multiply constraints on the right */ 5538 if (numFields) { 5539 for (f = 0; f < numFields; f++) { 5540 PetscInt oldOff = offsets[f]; 5541 5542 for (p = 0; p < numPoints; p++) { 5543 PetscInt cStart = newPointOffsets[f][p]; 5544 PetscInt b = points[2 * p]; 5545 PetscInt c, r, k; 5546 PetscInt dof; 5547 5548 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 5549 if (!dof) { 5550 continue; 5551 } 5552 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 5553 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 5554 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 5555 5556 for (r = 0; r < numIndices; r++) { 5557 for (c = 0; c < nCols; c++) { 5558 for (k = 0; k < dof; k++) { 5559 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 5560 } 5561 } 5562 } 5563 } 5564 else { 5565 /* copy this column as is */ 5566 for (r = 0; r < numIndices; r++) { 5567 for (c = 0; c < dof; c++) { 5568 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 5569 } 5570 } 5571 } 5572 oldOff += dof; 5573 } 5574 } 5575 } 5576 else { 5577 PetscInt oldOff = 0; 5578 for (p = 0; p < numPoints; p++) { 5579 PetscInt cStart = newPointOffsets[0][p]; 5580 PetscInt b = points[2 * p]; 5581 PetscInt c, r, k; 5582 PetscInt dof; 5583 5584 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 5585 if (!dof) { 5586 continue; 5587 } 5588 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 5589 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 5590 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 5591 5592 for (r = 0; r < numIndices; r++) { 5593 for (c = 0; c < nCols; c++) { 5594 for (k = 0; k < dof; k++) { 5595 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 5596 } 5597 } 5598 } 5599 } 5600 else { 5601 /* copy this column as is */ 5602 for (r = 0; r < numIndices; r++) { 5603 for (c = 0; c < dof; c++) { 5604 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 5605 } 5606 } 5607 } 5608 oldOff += dof; 5609 } 5610 } 5611 5612 if (multiplyLeft) { 5613 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 5614 ierr = PetscMemzero(newValues,newNumIndices*newNumIndices*sizeof(*newValues));CHKERRQ(ierr); 5615 /* multiply constraints transpose on the left */ 5616 if (numFields) { 5617 for (f = 0; f < numFields; f++) { 5618 PetscInt oldOff = offsets[f]; 5619 5620 for (p = 0; p < numPoints; p++) { 5621 PetscInt rStart = newPointOffsets[f][p]; 5622 PetscInt b = points[2 * p]; 5623 PetscInt c, r, k; 5624 PetscInt dof; 5625 5626 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 5627 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 5628 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 5629 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 5630 5631 for (r = 0; r < nRows; r++) { 5632 for (c = 0; c < newNumIndices; c++) { 5633 for (k = 0; k < dof; k++) { 5634 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 5635 } 5636 } 5637 } 5638 } 5639 else { 5640 /* copy this row as is */ 5641 for (r = 0; r < dof; r++) { 5642 for (c = 0; c < newNumIndices; c++) { 5643 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 5644 } 5645 } 5646 } 5647 oldOff += dof; 5648 } 5649 } 5650 } 5651 else { 5652 PetscInt oldOff = 0; 5653 5654 for (p = 0; p < numPoints; p++) { 5655 PetscInt rStart = newPointOffsets[0][p]; 5656 PetscInt b = points[2 * p]; 5657 PetscInt c, r, k; 5658 PetscInt dof; 5659 5660 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 5661 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 5662 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 5663 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 5664 5665 for (r = 0; r < nRows; r++) { 5666 for (c = 0; c < newNumIndices; c++) { 5667 for (k = 0; k < dof; k++) { 5668 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 5669 } 5670 } 5671 } 5672 } 5673 else { 5674 /* copy this row as is */ 5675 for (r = 0; r < dof; r++) { 5676 for (c = 0; c < newNumIndices; c++) { 5677 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 5678 } 5679 } 5680 } 5681 oldOff += dof; 5682 } 5683 } 5684 5685 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 5686 } 5687 else { 5688 newValues = tmpValues; 5689 } 5690 } 5691 5692 /* clean up */ 5693 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 5694 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 5695 5696 if (numFields) { 5697 for (f = 0; f < numFields; f++) { 5698 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 5699 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 5700 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 5701 } 5702 } 5703 else { 5704 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 5705 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 5706 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 5707 } 5708 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 5709 5710 /* output */ 5711 if (outPoints) { 5712 *outPoints = newPoints; 5713 } 5714 else { 5715 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5716 } 5717 if (outValues) { 5718 *outValues = newValues; 5719 } 5720 for (f = 0; f <= numFields; f++) { 5721 offsets[f] = newOffsets[f]; 5722 } 5723 PetscFunctionReturn(0); 5724 } 5725 5726 /*@C 5727 DMPlexGetClosureIndices - Get the global indices in a vector v for all points in the closure of the given point 5728 5729 Not collective 5730 5731 Input Parameters: 5732 + dm - The DM 5733 . section - The section describing the layout in v, or NULL to use the default section 5734 . globalSection - The section describing the parallel layout in v, or NULL to use the default section 5735 - point - The mesh point 5736 5737 Output parameters: 5738 + numIndices - The number of indices 5739 . indices - The indices 5740 - outOffsets - Field offset if not NULL 5741 5742 Note: Must call DMPlexRestoreClosureIndices() to free allocated memory 5743 5744 Level: advanced 5745 5746 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure() 5747 @*/ 5748 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices, PetscInt *outOffsets) 5749 { 5750 PetscSection clSection; 5751 IS clPoints; 5752 const PetscInt *clp; 5753 const PetscInt **perms[32] = {NULL}; 5754 PetscInt *points = NULL, *pointsNew; 5755 PetscInt numPoints, numPointsNew; 5756 PetscInt offsets[32]; 5757 PetscInt Nf, Nind, NindNew, off, globalOff, f, p; 5758 PetscErrorCode ierr; 5759 5760 PetscFunctionBegin; 5761 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5762 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5763 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 5764 if (numIndices) PetscValidPointer(numIndices, 4); 5765 PetscValidPointer(indices, 5); 5766 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5767 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 5768 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5769 /* Get points in closure */ 5770 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5771 /* Get number of indices and indices per field */ 5772 for (p = 0, Nind = 0; p < numPoints*2; p += 2) { 5773 PetscInt dof, fdof; 5774 5775 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5776 for (f = 0; f < Nf; ++f) { 5777 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5778 offsets[f+1] += fdof; 5779 } 5780 Nind += dof; 5781 } 5782 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 5783 if (Nf && offsets[Nf] != Nind) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Nind); 5784 if (!Nf) offsets[1] = Nind; 5785 /* Get dual space symmetries */ 5786 for (f = 0; f < PetscMax(1,Nf); f++) { 5787 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5788 else {ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5789 } 5790 /* Correct for hanging node constraints */ 5791 { 5792 ierr = DMPlexAnchorsModifyMat(dm, section, numPoints, Nind, points, perms, NULL, &numPointsNew, &NindNew, &pointsNew, NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 5793 if (numPointsNew) { 5794 for (f = 0; f < PetscMax(1,Nf); f++) { 5795 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5796 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5797 } 5798 for (f = 0; f < PetscMax(1,Nf); f++) { 5799 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section,f,numPointsNew,pointsNew,&perms[f],NULL);CHKERRQ(ierr);} 5800 else {ierr = PetscSectionGetPointSyms(section,numPointsNew,pointsNew,&perms[f],NULL);CHKERRQ(ierr);} 5801 } 5802 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5803 numPoints = numPointsNew; 5804 Nind = NindNew; 5805 points = pointsNew; 5806 } 5807 } 5808 /* Calculate indices */ 5809 ierr = DMGetWorkArray(dm, Nind, MPIU_INT, indices);CHKERRQ(ierr); 5810 if (Nf) { 5811 if (outOffsets) { 5812 PetscInt f; 5813 5814 for (f = 0; f <= Nf; f++) { 5815 outOffsets[f] = offsets[f]; 5816 } 5817 } 5818 for (p = 0; p < numPoints; p++) { 5819 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5820 DMPlexGetIndicesPointFields_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, perms, p, *indices); 5821 } 5822 } else { 5823 for (p = 0, off = 0; p < numPoints; p++) { 5824 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 5825 5826 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5827 DMPlexGetIndicesPoint_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, *indices); 5828 } 5829 } 5830 /* Cleanup points */ 5831 for (f = 0; f < PetscMax(1,Nf); f++) { 5832 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5833 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5834 } 5835 if (numPointsNew) { 5836 ierr = DMRestoreWorkArray(dm, 2*numPointsNew, MPIU_INT, &pointsNew);CHKERRQ(ierr); 5837 } else { 5838 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5839 } 5840 if (numIndices) *numIndices = Nind; 5841 PetscFunctionReturn(0); 5842 } 5843 5844 /*@C 5845 DMPlexRestoreClosureIndices - Restore the indices in a vector v for all points in the closure of the given point 5846 5847 Not collective 5848 5849 Input Parameters: 5850 + dm - The DM 5851 . section - The section describing the layout in v, or NULL to use the default section 5852 . globalSection - The section describing the parallel layout in v, or NULL to use the default section 5853 . point - The mesh point 5854 . numIndices - The number of indices 5855 . indices - The indices 5856 - outOffsets - Field offset if not NULL 5857 5858 Level: advanced 5859 5860 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure() 5861 @*/ 5862 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices,PetscInt *outOffsets) 5863 { 5864 PetscErrorCode ierr; 5865 5866 PetscFunctionBegin; 5867 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5868 PetscValidPointer(indices, 5); 5869 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 5870 PetscFunctionReturn(0); 5871 } 5872 5873 /*@C 5874 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 5875 5876 Not collective 5877 5878 Input Parameters: 5879 + dm - The DM 5880 . section - The section describing the layout in v, or NULL to use the default section 5881 . globalSection - The section describing the layout in v, or NULL to use the default global section 5882 . A - The matrix 5883 . point - The point in the DM 5884 . values - The array of values 5885 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 5886 5887 Fortran Notes: 5888 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 5889 5890 Level: intermediate 5891 5892 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 5893 @*/ 5894 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5895 { 5896 DM_Plex *mesh = (DM_Plex*) dm->data; 5897 PetscSection clSection; 5898 IS clPoints; 5899 PetscInt *points = NULL, *newPoints; 5900 const PetscInt *clp; 5901 PetscInt *indices; 5902 PetscInt offsets[32]; 5903 const PetscInt **perms[32] = {NULL}; 5904 const PetscScalar **flips[32] = {NULL}; 5905 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, p, f; 5906 PetscScalar *valCopy = NULL; 5907 PetscScalar *newValues; 5908 PetscErrorCode ierr; 5909 5910 PetscFunctionBegin; 5911 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5912 if (!section) {ierr = DMGetSection(dm, §ion);CHKERRQ(ierr);} 5913 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5914 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 5915 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 5916 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 5917 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5918 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5919 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5920 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5921 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 5922 PetscInt fdof; 5923 5924 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5925 for (f = 0; f < numFields; ++f) { 5926 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5927 offsets[f+1] += fdof; 5928 } 5929 numIndices += dof; 5930 } 5931 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 5932 5933 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[numFields], numIndices); 5934 /* Get symmetries */ 5935 for (f = 0; f < PetscMax(1,numFields); f++) { 5936 if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5937 else {ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5938 if (values && flips[f]) { /* may need to apply sign changes to the element matrix */ 5939 PetscInt foffset = offsets[f]; 5940 5941 for (p = 0; p < numPoints; p++) { 5942 PetscInt point = points[2*p], fdof; 5943 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 5944 5945 if (!numFields) { 5946 ierr = PetscSectionGetDof(section,point,&fdof);CHKERRQ(ierr); 5947 } else { 5948 ierr = PetscSectionGetFieldDof(section,point,f,&fdof);CHKERRQ(ierr); 5949 } 5950 if (flip) { 5951 PetscInt i, j, k; 5952 5953 if (!valCopy) { 5954 ierr = DMGetWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 5955 for (j = 0; j < numIndices * numIndices; j++) valCopy[j] = values[j]; 5956 values = valCopy; 5957 } 5958 for (i = 0; i < fdof; i++) { 5959 PetscScalar fval = flip[i]; 5960 5961 for (k = 0; k < numIndices; k++) { 5962 valCopy[numIndices * (foffset + i) + k] *= fval; 5963 valCopy[numIndices * k + (foffset + i)] *= fval; 5964 } 5965 } 5966 } 5967 foffset += fdof; 5968 } 5969 } 5970 } 5971 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,perms,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets,PETSC_TRUE);CHKERRQ(ierr); 5972 if (newNumPoints) { 5973 if (valCopy) { 5974 ierr = DMRestoreWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 5975 } 5976 for (f = 0; f < PetscMax(1,numFields); f++) { 5977 if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5978 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5979 } 5980 for (f = 0; f < PetscMax(1,numFields); f++) { 5981 if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,newNumPoints,newPoints,&perms[f],&flips[f]);CHKERRQ(ierr);} 5982 else {ierr = PetscSectionGetPointSyms(section,newNumPoints,newPoints,&perms[f],&flips[f]);CHKERRQ(ierr);} 5983 } 5984 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5985 numPoints = newNumPoints; 5986 numIndices = newNumIndices; 5987 points = newPoints; 5988 values = newValues; 5989 } 5990 ierr = DMGetWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr); 5991 if (numFields) { 5992 PetscBool useFieldOffsets; 5993 5994 ierr = PetscSectionGetUseFieldOffsets(globalSection, &useFieldOffsets);CHKERRQ(ierr); 5995 if (useFieldOffsets) { 5996 for (p = 0; p < numPoints; p++) { 5997 DMPlexGetIndicesPointFieldsSplit_Internal(section, globalSection, points[2*p], offsets, PETSC_FALSE, perms, p, indices); 5998 } 5999 } else { 6000 for (p = 0; p < numPoints; p++) { 6001 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 6002 DMPlexGetIndicesPointFields_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, perms, p, indices); 6003 } 6004 } 6005 } else { 6006 for (p = 0, off = 0; p < numPoints; p++) { 6007 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 6008 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 6009 DMPlexGetIndicesPoint_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, indices); 6010 } 6011 } 6012 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 6013 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 6014 if (mesh->printFEM > 1) { 6015 PetscInt i; 6016 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 6017 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 6018 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6019 } 6020 if (ierr) { 6021 PetscMPIInt rank; 6022 PetscErrorCode ierr2; 6023 6024 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 6025 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 6026 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 6027 ierr2 = DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr2); 6028 CHKERRQ(ierr); 6029 } 6030 for (f = 0; f < PetscMax(1,numFields); f++) { 6031 if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 6032 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 6033 } 6034 if (newNumPoints) { 6035 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 6036 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6037 } 6038 else { 6039 if (valCopy) { 6040 ierr = DMRestoreWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 6041 } 6042 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6043 } 6044 ierr = DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr); 6045 PetscFunctionReturn(0); 6046 } 6047 6048 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 6049 { 6050 DM_Plex *mesh = (DM_Plex*) dmf->data; 6051 PetscInt *fpoints = NULL, *ftotpoints = NULL; 6052 PetscInt *cpoints = NULL; 6053 PetscInt *findices, *cindices; 6054 PetscInt foffsets[32], coffsets[32]; 6055 CellRefiner cellRefiner; 6056 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 6057 PetscErrorCode ierr; 6058 6059 PetscFunctionBegin; 6060 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 6061 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 6062 if (!fsection) {ierr = DMGetSection(dmf, &fsection);CHKERRQ(ierr);} 6063 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 6064 if (!csection) {ierr = DMGetSection(dmc, &csection);CHKERRQ(ierr);} 6065 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 6066 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 6067 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 6068 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 6069 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 6070 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 6071 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 6072 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6073 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6074 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6075 /* Column indices */ 6076 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 6077 maxFPoints = numCPoints; 6078 /* Compress out points not in the section */ 6079 /* TODO: Squeeze out points with 0 dof as well */ 6080 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 6081 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 6082 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 6083 cpoints[q*2] = cpoints[p]; 6084 cpoints[q*2+1] = cpoints[p+1]; 6085 ++q; 6086 } 6087 } 6088 numCPoints = q; 6089 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 6090 PetscInt fdof; 6091 6092 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 6093 if (!dof) continue; 6094 for (f = 0; f < numFields; ++f) { 6095 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 6096 coffsets[f+1] += fdof; 6097 } 6098 numCIndices += dof; 6099 } 6100 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 6101 /* Row indices */ 6102 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 6103 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 6104 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6105 for (r = 0, q = 0; r < numSubcells; ++r) { 6106 /* TODO Map from coarse to fine cells */ 6107 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6108 /* Compress out points not in the section */ 6109 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 6110 for (p = 0; p < numFPoints*2; p += 2) { 6111 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 6112 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 6113 if (!dof) continue; 6114 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 6115 if (s < q) continue; 6116 ftotpoints[q*2] = fpoints[p]; 6117 ftotpoints[q*2+1] = fpoints[p+1]; 6118 ++q; 6119 } 6120 } 6121 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6122 } 6123 numFPoints = q; 6124 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 6125 PetscInt fdof; 6126 6127 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 6128 if (!dof) continue; 6129 for (f = 0; f < numFields; ++f) { 6130 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 6131 foffsets[f+1] += fdof; 6132 } 6133 numFIndices += dof; 6134 } 6135 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 6136 6137 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 6138 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 6139 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 6140 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 6141 if (numFields) { 6142 const PetscInt **permsF[32] = {NULL}; 6143 const PetscInt **permsC[32] = {NULL}; 6144 6145 for (f = 0; f < numFields; f++) { 6146 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 6147 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6148 } 6149 for (p = 0; p < numFPoints; p++) { 6150 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6151 ierr = DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, findices);CHKERRQ(ierr); 6152 } 6153 for (p = 0; p < numCPoints; p++) { 6154 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 6155 ierr = DMPlexGetIndicesPointFields_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cindices);CHKERRQ(ierr); 6156 } 6157 for (f = 0; f < numFields; f++) { 6158 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 6159 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6160 } 6161 } else { 6162 const PetscInt **permsF = NULL; 6163 const PetscInt **permsC = NULL; 6164 6165 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 6166 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6167 for (p = 0, off = 0; p < numFPoints; p++) { 6168 const PetscInt *perm = permsF ? permsF[p] : NULL; 6169 6170 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6171 ierr = DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, findices);CHKERRQ(ierr); 6172 } 6173 for (p = 0, off = 0; p < numCPoints; p++) { 6174 const PetscInt *perm = permsC ? permsC[p] : NULL; 6175 6176 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 6177 ierr = DMPlexGetIndicesPoint_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cindices);CHKERRQ(ierr); 6178 } 6179 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 6180 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6181 } 6182 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 6183 /* TODO: flips */ 6184 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 6185 if (ierr) { 6186 PetscMPIInt rank; 6187 PetscErrorCode ierr2; 6188 6189 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 6190 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 6191 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 6192 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 6193 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 6194 CHKERRQ(ierr); 6195 } 6196 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6197 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 6198 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 6199 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 6200 PetscFunctionReturn(0); 6201 } 6202 6203 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 6204 { 6205 PetscInt *fpoints = NULL, *ftotpoints = NULL; 6206 PetscInt *cpoints = NULL; 6207 PetscInt foffsets[32], coffsets[32]; 6208 CellRefiner cellRefiner; 6209 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 6210 PetscErrorCode ierr; 6211 6212 PetscFunctionBegin; 6213 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 6214 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 6215 if (!fsection) {ierr = DMGetSection(dmf, &fsection);CHKERRQ(ierr);} 6216 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 6217 if (!csection) {ierr = DMGetSection(dmc, &csection);CHKERRQ(ierr);} 6218 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 6219 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 6220 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 6221 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 6222 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 6223 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 6224 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6225 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6226 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6227 /* Column indices */ 6228 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 6229 maxFPoints = numCPoints; 6230 /* Compress out points not in the section */ 6231 /* TODO: Squeeze out points with 0 dof as well */ 6232 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 6233 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 6234 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 6235 cpoints[q*2] = cpoints[p]; 6236 cpoints[q*2+1] = cpoints[p+1]; 6237 ++q; 6238 } 6239 } 6240 numCPoints = q; 6241 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 6242 PetscInt fdof; 6243 6244 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 6245 if (!dof) continue; 6246 for (f = 0; f < numFields; ++f) { 6247 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 6248 coffsets[f+1] += fdof; 6249 } 6250 numCIndices += dof; 6251 } 6252 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 6253 /* Row indices */ 6254 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 6255 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 6256 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6257 for (r = 0, q = 0; r < numSubcells; ++r) { 6258 /* TODO Map from coarse to fine cells */ 6259 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6260 /* Compress out points not in the section */ 6261 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 6262 for (p = 0; p < numFPoints*2; p += 2) { 6263 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 6264 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 6265 if (!dof) continue; 6266 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 6267 if (s < q) continue; 6268 ftotpoints[q*2] = fpoints[p]; 6269 ftotpoints[q*2+1] = fpoints[p+1]; 6270 ++q; 6271 } 6272 } 6273 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6274 } 6275 numFPoints = q; 6276 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 6277 PetscInt fdof; 6278 6279 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 6280 if (!dof) continue; 6281 for (f = 0; f < numFields; ++f) { 6282 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 6283 foffsets[f+1] += fdof; 6284 } 6285 numFIndices += dof; 6286 } 6287 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 6288 6289 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 6290 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 6291 if (numFields) { 6292 const PetscInt **permsF[32] = {NULL}; 6293 const PetscInt **permsC[32] = {NULL}; 6294 6295 for (f = 0; f < numFields; f++) { 6296 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 6297 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6298 } 6299 for (p = 0; p < numFPoints; p++) { 6300 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6301 DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, findices); 6302 } 6303 for (p = 0; p < numCPoints; p++) { 6304 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 6305 DMPlexGetIndicesPointFields_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cindices); 6306 } 6307 for (f = 0; f < numFields; f++) { 6308 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 6309 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6310 } 6311 } else { 6312 const PetscInt **permsF = NULL; 6313 const PetscInt **permsC = NULL; 6314 6315 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 6316 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6317 for (p = 0, off = 0; p < numFPoints; p++) { 6318 const PetscInt *perm = permsF ? permsF[p] : NULL; 6319 6320 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6321 DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, findices); 6322 } 6323 for (p = 0, off = 0; p < numCPoints; p++) { 6324 const PetscInt *perm = permsC ? permsC[p] : NULL; 6325 6326 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 6327 DMPlexGetIndicesPoint_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cindices); 6328 } 6329 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 6330 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6331 } 6332 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6333 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 6334 PetscFunctionReturn(0); 6335 } 6336 6337 /*@ 6338 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 6339 6340 Input Parameter: 6341 . dm - The DMPlex object 6342 6343 Output Parameters: 6344 + cMax - The first hybrid cell 6345 . fMax - The first hybrid face 6346 . eMax - The first hybrid edge 6347 - vMax - The first hybrid vertex 6348 6349 Level: developer 6350 6351 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 6352 @*/ 6353 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 6354 { 6355 DM_Plex *mesh = (DM_Plex*) dm->data; 6356 PetscInt dim; 6357 PetscErrorCode ierr; 6358 6359 PetscFunctionBegin; 6360 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6361 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6362 if (dim < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM dimension not yet set"); 6363 if (cMax) *cMax = mesh->hybridPointMax[dim]; 6364 if (fMax) *fMax = mesh->hybridPointMax[PetscMax(dim-1,0)]; 6365 if (eMax) *eMax = mesh->hybridPointMax[1]; 6366 if (vMax) *vMax = mesh->hybridPointMax[0]; 6367 PetscFunctionReturn(0); 6368 } 6369 6370 static PetscErrorCode DMPlexCreateDimStratum(DM dm, DMLabel depthLabel, DMLabel dimLabel, PetscInt d, PetscInt dMax) 6371 { 6372 IS is, his; 6373 PetscInt first = 0, stride; 6374 PetscBool isStride; 6375 PetscErrorCode ierr; 6376 6377 PetscFunctionBegin; 6378 ierr = DMLabelGetStratumIS(depthLabel, d, &is);CHKERRQ(ierr); 6379 ierr = PetscObjectTypeCompare((PetscObject) is, ISSTRIDE, &isStride);CHKERRQ(ierr); 6380 if (isStride) { 6381 ierr = ISStrideGetInfo(is, &first, &stride);CHKERRQ(ierr); 6382 } 6383 if (is && (!isStride || stride != 1)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM is not stratified: depth %D IS is not contiguous", d); 6384 ierr = ISCreateStride(PETSC_COMM_SELF, (dMax - first), first, 1, &his);CHKERRQ(ierr); 6385 ierr = DMLabelSetStratumIS(dimLabel, d, his);CHKERRQ(ierr); 6386 ierr = ISDestroy(&his);CHKERRQ(ierr); 6387 ierr = ISDestroy(&is);CHKERRQ(ierr); 6388 PetscFunctionReturn(0); 6389 } 6390 6391 /*@ 6392 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 6393 6394 Input Parameters: 6395 . dm - The DMPlex object 6396 . cMax - The first hybrid cell 6397 . fMax - The first hybrid face 6398 . eMax - The first hybrid edge 6399 - vMax - The first hybrid vertex 6400 6401 Level: developer 6402 6403 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 6404 @*/ 6405 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 6406 { 6407 DM_Plex *mesh = (DM_Plex*) dm->data; 6408 PetscInt dim; 6409 PetscErrorCode ierr; 6410 6411 PetscFunctionBegin; 6412 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6413 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6414 if (dim < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM dimension not yet set"); 6415 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 6416 if (fMax >= 0) mesh->hybridPointMax[PetscMax(dim-1,0)] = fMax; 6417 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 6418 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 6419 PetscFunctionReturn(0); 6420 } 6421 6422 /*@C 6423 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 6424 6425 Input Parameter: 6426 . dm - The DMPlex object 6427 6428 Output Parameter: 6429 . cellHeight - The height of a cell 6430 6431 Level: developer 6432 6433 .seealso DMPlexSetVTKCellHeight() 6434 @*/ 6435 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 6436 { 6437 DM_Plex *mesh = (DM_Plex*) dm->data; 6438 6439 PetscFunctionBegin; 6440 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6441 PetscValidPointer(cellHeight, 2); 6442 *cellHeight = mesh->vtkCellHeight; 6443 PetscFunctionReturn(0); 6444 } 6445 6446 /*@C 6447 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 6448 6449 Input Parameters: 6450 + dm - The DMPlex object 6451 - cellHeight - The height of a cell 6452 6453 Level: developer 6454 6455 .seealso DMPlexGetVTKCellHeight() 6456 @*/ 6457 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 6458 { 6459 DM_Plex *mesh = (DM_Plex*) dm->data; 6460 6461 PetscFunctionBegin; 6462 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6463 mesh->vtkCellHeight = cellHeight; 6464 PetscFunctionReturn(0); 6465 } 6466 6467 /* We can easily have a form that takes an IS instead */ 6468 static PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 6469 { 6470 PetscSection section, globalSection; 6471 PetscInt *numbers, p; 6472 PetscErrorCode ierr; 6473 6474 PetscFunctionBegin; 6475 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 6476 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 6477 for (p = pStart; p < pEnd; ++p) { 6478 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 6479 } 6480 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 6481 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 6482 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 6483 for (p = pStart; p < pEnd; ++p) { 6484 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 6485 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 6486 else numbers[p-pStart] += shift; 6487 } 6488 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 6489 if (globalSize) { 6490 PetscLayout layout; 6491 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 6492 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 6493 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 6494 } 6495 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6496 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 6497 PetscFunctionReturn(0); 6498 } 6499 6500 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 6501 { 6502 PetscInt cellHeight, cStart, cEnd, cMax; 6503 PetscErrorCode ierr; 6504 6505 PetscFunctionBegin; 6506 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 6507 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 6508 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 6509 if (cMax >= 0 && !includeHybrid) cEnd = PetscMin(cEnd, cMax); 6510 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 6511 PetscFunctionReturn(0); 6512 } 6513 6514 /*@ 6515 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 6516 6517 Input Parameter: 6518 . dm - The DMPlex object 6519 6520 Output Parameter: 6521 . globalCellNumbers - Global cell numbers for all cells on this process 6522 6523 Level: developer 6524 6525 .seealso DMPlexGetVertexNumbering() 6526 @*/ 6527 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 6528 { 6529 DM_Plex *mesh = (DM_Plex*) dm->data; 6530 PetscErrorCode ierr; 6531 6532 PetscFunctionBegin; 6533 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6534 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 6535 *globalCellNumbers = mesh->globalCellNumbers; 6536 PetscFunctionReturn(0); 6537 } 6538 6539 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 6540 { 6541 PetscInt vStart, vEnd, vMax; 6542 PetscErrorCode ierr; 6543 6544 PetscFunctionBegin; 6545 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6546 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6547 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 6548 if (vMax >= 0 && !includeHybrid) vEnd = PetscMin(vEnd, vMax); 6549 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 6550 PetscFunctionReturn(0); 6551 } 6552 6553 /*@ 6554 DMPlexGetVertexNumbering - Get a global certex numbering for all vertices on this process 6555 6556 Input Parameter: 6557 . dm - The DMPlex object 6558 6559 Output Parameter: 6560 . globalVertexNumbers - Global vertex numbers for all vertices on this process 6561 6562 Level: developer 6563 6564 .seealso DMPlexGetCellNumbering() 6565 @*/ 6566 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 6567 { 6568 DM_Plex *mesh = (DM_Plex*) dm->data; 6569 PetscErrorCode ierr; 6570 6571 PetscFunctionBegin; 6572 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6573 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 6574 *globalVertexNumbers = mesh->globalVertexNumbers; 6575 PetscFunctionReturn(0); 6576 } 6577 6578 /*@ 6579 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 6580 6581 Input Parameter: 6582 . dm - The DMPlex object 6583 6584 Output Parameter: 6585 . globalPointNumbers - Global numbers for all points on this process 6586 6587 Level: developer 6588 6589 .seealso DMPlexGetCellNumbering() 6590 @*/ 6591 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 6592 { 6593 IS nums[4]; 6594 PetscInt depths[4]; 6595 PetscInt depth, d, shift = 0; 6596 PetscErrorCode ierr; 6597 6598 PetscFunctionBegin; 6599 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6600 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6601 /* For unstratified meshes use dim instead of depth */ 6602 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 6603 depths[0] = depth; depths[1] = 0; 6604 for (d = 2; d <= depth; ++d) depths[d] = depth-d+1; 6605 for (d = 0; d <= depth; ++d) { 6606 PetscInt pStart, pEnd, gsize; 6607 6608 ierr = DMPlexGetDepthStratum(dm, depths[d], &pStart, &pEnd);CHKERRQ(ierr); 6609 ierr = DMPlexCreateNumbering_Private(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 6610 shift += gsize; 6611 } 6612 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 6613 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 6614 PetscFunctionReturn(0); 6615 } 6616 6617 6618 /*@ 6619 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 6620 6621 Input Parameter: 6622 . dm - The DMPlex object 6623 6624 Output Parameter: 6625 . ranks - The rank field 6626 6627 Options Database Keys: 6628 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 6629 6630 Level: intermediate 6631 6632 .seealso: DMView() 6633 @*/ 6634 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 6635 { 6636 DM rdm; 6637 PetscDS prob; 6638 PetscFE fe; 6639 PetscScalar *r; 6640 PetscMPIInt rank; 6641 PetscInt dim, cStart, cEnd, c; 6642 PetscErrorCode ierr; 6643 6644 PetscFunctionBeginUser; 6645 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6646 PetscValidPointer(ranks, 2); 6647 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 6648 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 6649 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 6650 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 6651 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 6652 ierr = DMGetDS(rdm, &prob);CHKERRQ(ierr); 6653 ierr = PetscDSSetDiscretization(prob, 0, (PetscObject) fe);CHKERRQ(ierr); 6654 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 6655 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6656 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 6657 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 6658 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 6659 for (c = cStart; c < cEnd; ++c) { 6660 PetscScalar *lr; 6661 6662 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 6663 *lr = rank; 6664 } 6665 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 6666 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 6667 PetscFunctionReturn(0); 6668 } 6669 6670 /*@ 6671 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 6672 6673 Input Parameters: 6674 + dm - The DMPlex 6675 - label - The DMLabel 6676 6677 Output Parameter: 6678 . val - The label value field 6679 6680 Options Database Keys: 6681 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 6682 6683 Level: intermediate 6684 6685 .seealso: DMView() 6686 @*/ 6687 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 6688 { 6689 DM rdm; 6690 PetscDS prob; 6691 PetscFE fe; 6692 PetscScalar *v; 6693 PetscInt dim, cStart, cEnd, c; 6694 PetscErrorCode ierr; 6695 6696 PetscFunctionBeginUser; 6697 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6698 PetscValidPointer(label, 2); 6699 PetscValidPointer(val, 3); 6700 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 6701 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 6702 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 6703 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 6704 ierr = DMGetDS(rdm, &prob);CHKERRQ(ierr); 6705 ierr = PetscDSSetDiscretization(prob, 0, (PetscObject) fe);CHKERRQ(ierr); 6706 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 6707 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6708 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 6709 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 6710 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 6711 for (c = cStart; c < cEnd; ++c) { 6712 PetscScalar *lv; 6713 PetscInt cval; 6714 6715 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 6716 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 6717 *lv = cval; 6718 } 6719 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 6720 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 6721 PetscFunctionReturn(0); 6722 } 6723 6724 /*@ 6725 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 6726 6727 Input Parameter: 6728 . dm - The DMPlex object 6729 6730 Note: This is a useful diagnostic when creating meshes programmatically. 6731 6732 Level: developer 6733 6734 .seealso: DMCreate(), DMPlexCheckSkeleton(), DMPlexCheckFaces() 6735 @*/ 6736 PetscErrorCode DMPlexCheckSymmetry(DM dm) 6737 { 6738 PetscSection coneSection, supportSection; 6739 const PetscInt *cone, *support; 6740 PetscInt coneSize, c, supportSize, s; 6741 PetscInt pStart, pEnd, p, csize, ssize; 6742 PetscErrorCode ierr; 6743 6744 PetscFunctionBegin; 6745 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6746 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 6747 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 6748 /* Check that point p is found in the support of its cone points, and vice versa */ 6749 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6750 for (p = pStart; p < pEnd; ++p) { 6751 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 6752 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 6753 for (c = 0; c < coneSize; ++c) { 6754 PetscBool dup = PETSC_FALSE; 6755 PetscInt d; 6756 for (d = c-1; d >= 0; --d) { 6757 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 6758 } 6759 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 6760 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 6761 for (s = 0; s < supportSize; ++s) { 6762 if (support[s] == p) break; 6763 } 6764 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 6765 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 6766 for (s = 0; s < coneSize; ++s) { 6767 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 6768 } 6769 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6770 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 6771 for (s = 0; s < supportSize; ++s) { 6772 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 6773 } 6774 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6775 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 6776 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 6777 } 6778 } 6779 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 6780 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 6781 for (s = 0; s < supportSize; ++s) { 6782 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6783 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6784 for (c = 0; c < coneSize; ++c) { 6785 if (cone[c] == p) break; 6786 } 6787 if (c >= coneSize) { 6788 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 6789 for (c = 0; c < supportSize; ++c) { 6790 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 6791 } 6792 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6793 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 6794 for (c = 0; c < coneSize; ++c) { 6795 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 6796 } 6797 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6798 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 6799 } 6800 } 6801 } 6802 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 6803 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 6804 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 6805 PetscFunctionReturn(0); 6806 } 6807 6808 /*@ 6809 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 6810 6811 Input Parameters: 6812 + dm - The DMPlex object 6813 . isSimplex - Are the cells simplices or tensor products 6814 - cellHeight - Normally 0 6815 6816 Note: This is a useful diagnostic when creating meshes programmatically. 6817 6818 Level: developer 6819 6820 .seealso: DMCreate(), DMPlexCheckSymmetry(), DMPlexCheckFaces() 6821 @*/ 6822 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight) 6823 { 6824 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 6825 PetscErrorCode ierr; 6826 6827 PetscFunctionBegin; 6828 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6829 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6830 switch (dim) { 6831 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 6832 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 6833 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 6834 default: 6835 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %D", dim); 6836 } 6837 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6838 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 6839 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 6840 cMax = cMax >= 0 ? cMax : cEnd; 6841 for (c = cStart; c < cMax; ++c) { 6842 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 6843 6844 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6845 for (cl = 0; cl < closureSize*2; cl += 2) { 6846 const PetscInt p = closure[cl]; 6847 if ((p >= vStart) && (p < vEnd)) ++coneSize; 6848 } 6849 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6850 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has %D vertices != %D", c, coneSize, numCorners); 6851 } 6852 for (c = cMax; c < cEnd; ++c) { 6853 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 6854 6855 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6856 for (cl = 0; cl < closureSize*2; cl += 2) { 6857 const PetscInt p = closure[cl]; 6858 if ((p >= vStart) && (p < vEnd)) ++coneSize; 6859 } 6860 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6861 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %D has %D vertices > %D", c, coneSize, numHybridCorners); 6862 } 6863 PetscFunctionReturn(0); 6864 } 6865 6866 /*@ 6867 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 6868 6869 Input Parameters: 6870 + dm - The DMPlex object 6871 . isSimplex - Are the cells simplices or tensor products 6872 - cellHeight - Normally 0 6873 6874 Note: This is a useful diagnostic when creating meshes programmatically. 6875 6876 Level: developer 6877 6878 .seealso: DMCreate(), DMPlexCheckSymmetry(), DMPlexCheckSkeleton() 6879 @*/ 6880 PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight) 6881 { 6882 PetscInt pMax[4]; 6883 PetscInt dim, vStart, vEnd, cStart, cEnd, c, h; 6884 PetscErrorCode ierr; 6885 6886 PetscFunctionBegin; 6887 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6888 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6889 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6890 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 6891 for (h = cellHeight; h < dim; ++h) { 6892 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 6893 for (c = cStart; c < cEnd; ++c) { 6894 const PetscInt *cone, *ornt, *faces; 6895 PetscInt numFaces, faceSize, coneSize,f; 6896 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 6897 6898 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 6899 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 6900 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6901 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6902 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6903 for (cl = 0; cl < closureSize*2; cl += 2) { 6904 const PetscInt p = closure[cl]; 6905 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 6906 } 6907 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 6908 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has %D faces but should have %D", c, coneSize, numFaces); 6909 for (f = 0; f < numFaces; ++f) { 6910 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 6911 6912 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 6913 for (cl = 0; cl < fclosureSize*2; cl += 2) { 6914 const PetscInt p = fclosure[cl]; 6915 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 6916 } 6917 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); 6918 for (v = 0; v < fnumCorners; ++v) { 6919 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]); 6920 } 6921 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 6922 } 6923 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 6924 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6925 } 6926 } 6927 PetscFunctionReturn(0); 6928 } 6929 6930 static PetscErrorCode DMPlexAreAllConePointsInArray_Private(DM dm, PetscInt p, PetscInt npoints, const PetscInt *points, PetscInt *missingPoint) 6931 { 6932 PetscInt i,l,n; 6933 const PetscInt *cone; 6934 PetscErrorCode ierr; 6935 6936 PetscFunctionBegin; 6937 *missingPoint = -1; 6938 ierr = DMPlexGetConeSize(dm, p, &n);CHKERRQ(ierr); 6939 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 6940 for (i=0; i<n; i++) { 6941 ierr = PetscFindInt(cone[i], npoints, points, &l);CHKERRQ(ierr); 6942 if (l < 0) { 6943 *missingPoint = cone[i]; 6944 break; 6945 } 6946 } 6947 PetscFunctionReturn(0); 6948 } 6949 6950 /*@ 6951 DMPlexCheckPointSF - Check that several sufficient conditions are met for the point SF of this plex. 6952 6953 Input Parameters: 6954 . dm - The DMPlex object 6955 6956 Note: This is mainly intended for debugging/testing purposes. 6957 6958 Level: developer 6959 6960 .seealso: DMGetPointSF(), DMPlexCheckSymmetry(), DMPlexCheckSkeleton(), DMPlexCheckFaces() 6961 @*/ 6962 PetscErrorCode DMPlexCheckPointSF(DM dm) 6963 { 6964 PetscSF sf; 6965 PetscInt d,depth,i,nleaves,p,plo,phi,missingPoint; 6966 const PetscInt *locals; 6967 PetscErrorCode ierr; 6968 6969 PetscFunctionBegin; 6970 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6971 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6972 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6973 ierr = PetscSFGetGraph(sf, NULL, &nleaves, &locals, NULL);CHKERRQ(ierr); 6974 6975 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 6976 ierr = DMPlexGetVTKCellHeight(dm, &d);CHKERRQ(ierr); 6977 ierr = DMPlexGetHeightStratum(dm, d, &plo, &phi);CHKERRQ(ierr); 6978 for (i=0; i<nleaves; i++) { 6979 p = locals[i]; 6980 if (p >= plo && p < phi) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "point SF contains %d which is a cell",p); 6981 } 6982 6983 /* 2) if some point is in interface, then all its cone points must be also in interface */ 6984 for (i=0; i<nleaves; i++) { 6985 p = locals[i]; 6986 ierr = DMPlexAreAllConePointsInArray_Private(dm, p, nleaves, locals, &missingPoint);CHKERRQ(ierr); 6987 if (missingPoint >= 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "point SF contains %d but not %d from its cone",p,missingPoint); 6988 } 6989 PetscFunctionReturn(0); 6990 } 6991 6992 /* Pointwise interpolation 6993 Just code FEM for now 6994 u^f = I u^c 6995 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 6996 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 6997 I_{ij} = psi^f_i phi^c_j 6998 */ 6999 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 7000 { 7001 PetscSection gsc, gsf; 7002 PetscInt m, n; 7003 void *ctx; 7004 DM cdm; 7005 PetscBool regular, ismatis; 7006 PetscErrorCode ierr; 7007 7008 PetscFunctionBegin; 7009 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 7010 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 7011 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 7012 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 7013 7014 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 7015 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 7016 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 7017 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 7018 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 7019 7020 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 7021 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 7022 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 7023 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 7024 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 7025 if (scaling) { 7026 /* Use naive scaling */ 7027 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 7028 } 7029 PetscFunctionReturn(0); 7030 } 7031 7032 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 7033 { 7034 PetscErrorCode ierr; 7035 VecScatter ctx; 7036 7037 PetscFunctionBegin; 7038 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 7039 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 7040 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 7041 PetscFunctionReturn(0); 7042 } 7043 7044 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 7045 { 7046 PetscSection gsc, gsf; 7047 PetscInt m, n; 7048 void *ctx; 7049 DM cdm; 7050 PetscBool regular; 7051 PetscErrorCode ierr; 7052 7053 PetscFunctionBegin; 7054 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 7055 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 7056 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 7057 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 7058 7059 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 7060 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 7061 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 7062 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 7063 7064 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 7065 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 7066 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 7067 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 7068 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 7069 PetscFunctionReturn(0); 7070 } 7071 7072 PetscErrorCode DMCreateDefaultSection_Plex(DM dm) 7073 { 7074 PetscSection section; 7075 IS *bcPoints, *bcComps; 7076 PetscBool *isFE; 7077 PetscInt *bcFields, *numComp, *numDof; 7078 PetscInt depth, dim, numBd, numBC = 0, numFields, bd, bc = 0, f; 7079 PetscInt cStart, cEnd, cEndInterior; 7080 PetscErrorCode ierr; 7081 7082 PetscFunctionBegin; 7083 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 7084 /* FE and FV boundary conditions are handled slightly differently */ 7085 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 7086 for (f = 0; f < numFields; ++f) { 7087 PetscObject obj; 7088 PetscClassId id; 7089 7090 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 7091 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 7092 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 7093 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 7094 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %D", f); 7095 } 7096 /* Allocate boundary point storage for FEM boundaries */ 7097 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7098 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 7099 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7100 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 7101 ierr = PetscDSGetNumBoundary(dm->prob, &numBd);CHKERRQ(ierr); 7102 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)"); 7103 for (bd = 0; bd < numBd; ++bd) { 7104 PetscInt field; 7105 DMBoundaryConditionType type; 7106 const char *labelName; 7107 DMLabel label; 7108 7109 ierr = PetscDSGetBoundary(dm->prob, bd, &type, NULL, &labelName, &field, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 7110 ierr = DMGetLabel(dm,labelName,&label);CHKERRQ(ierr); 7111 if (label && isFE[field] && (type & DM_BC_ESSENTIAL)) ++numBC; 7112 } 7113 /* Add ghost cell boundaries for FVM */ 7114 for (f = 0; f < numFields; ++f) if (!isFE[f] && cEndInterior >= 0) ++numBC; 7115 ierr = PetscCalloc3(numBC,&bcFields,numBC,&bcPoints,numBC,&bcComps);CHKERRQ(ierr); 7116 /* Constrain ghost cells for FV */ 7117 for (f = 0; f < numFields; ++f) { 7118 PetscInt *newidx, c; 7119 7120 if (isFE[f] || cEndInterior < 0) continue; 7121 ierr = PetscMalloc1(cEnd-cEndInterior,&newidx);CHKERRQ(ierr); 7122 for (c = cEndInterior; c < cEnd; ++c) newidx[c-cEndInterior] = c; 7123 bcFields[bc] = f; 7124 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), cEnd-cEndInterior, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 7125 } 7126 /* Handle FEM Dirichlet boundaries */ 7127 for (bd = 0; bd < numBd; ++bd) { 7128 const char *bdLabel; 7129 DMLabel label; 7130 const PetscInt *comps; 7131 const PetscInt *values; 7132 PetscInt bd2, field, numComps, numValues; 7133 DMBoundaryConditionType type; 7134 PetscBool duplicate = PETSC_FALSE; 7135 7136 ierr = PetscDSGetBoundary(dm->prob, bd, &type, NULL, &bdLabel, &field, &numComps, &comps, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 7137 ierr = DMGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 7138 if (!isFE[field] || !label) continue; 7139 /* Only want to modify label once */ 7140 for (bd2 = 0; bd2 < bd; ++bd2) { 7141 const char *bdname; 7142 ierr = PetscDSGetBoundary(dm->prob, bd2, NULL, NULL, &bdname, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 7143 ierr = PetscStrcmp(bdname, bdLabel, &duplicate);CHKERRQ(ierr); 7144 if (duplicate) break; 7145 } 7146 if (!duplicate && (isFE[field])) { 7147 /* don't complete cells, which are just present to give orientation to the boundary */ 7148 ierr = DMPlexLabelComplete(dm, label);CHKERRQ(ierr); 7149 } 7150 /* Filter out cells, if you actually want to constrain cells you need to do things by hand right now */ 7151 if (type & DM_BC_ESSENTIAL) { 7152 PetscInt *newidx; 7153 PetscInt n, newn = 0, p, v; 7154 7155 bcFields[bc] = field; 7156 if (numComps) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), numComps, comps, PETSC_COPY_VALUES, &bcComps[bc]);CHKERRQ(ierr);} 7157 for (v = 0; v < numValues; ++v) { 7158 IS tmp; 7159 const PetscInt *idx; 7160 7161 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 7162 if (!tmp) continue; 7163 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 7164 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 7165 if (isFE[field]) { 7166 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) ++newn; 7167 } else { 7168 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) ++newn; 7169 } 7170 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 7171 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 7172 } 7173 ierr = PetscMalloc1(newn,&newidx);CHKERRQ(ierr); 7174 newn = 0; 7175 for (v = 0; v < numValues; ++v) { 7176 IS tmp; 7177 const PetscInt *idx; 7178 7179 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 7180 if (!tmp) continue; 7181 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 7182 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 7183 if (isFE[field]) { 7184 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) newidx[newn++] = idx[p]; 7185 } else { 7186 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) newidx[newn++] = idx[p]; 7187 } 7188 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 7189 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 7190 } 7191 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), newn, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 7192 } 7193 } 7194 /* Handle discretization */ 7195 ierr = PetscCalloc2(numFields,&numComp,numFields*(dim+1),&numDof);CHKERRQ(ierr); 7196 for (f = 0; f < numFields; ++f) { 7197 PetscObject obj; 7198 7199 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 7200 if (isFE[f]) { 7201 PetscFE fe = (PetscFE) obj; 7202 const PetscInt *numFieldDof; 7203 PetscInt d; 7204 7205 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 7206 ierr = PetscFEGetNumDof(fe, &numFieldDof);CHKERRQ(ierr); 7207 for (d = 0; d < dim+1; ++d) numDof[f*(dim+1)+d] = numFieldDof[d]; 7208 } else { 7209 PetscFV fv = (PetscFV) obj; 7210 7211 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 7212 numDof[f*(dim+1)+dim] = numComp[f]; 7213 } 7214 } 7215 for (f = 0; f < numFields; ++f) { 7216 PetscInt d; 7217 for (d = 1; d < dim; ++d) { 7218 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."); 7219 } 7220 } 7221 ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcComps, bcPoints, NULL, §ion);CHKERRQ(ierr); 7222 for (f = 0; f < numFields; ++f) { 7223 PetscFE fe; 7224 const char *name; 7225 7226 ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 7227 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 7228 ierr = PetscSectionSetFieldName(section, f, name);CHKERRQ(ierr); 7229 } 7230 ierr = DMSetSection(dm, section);CHKERRQ(ierr); 7231 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7232 for (bc = 0; bc < numBC; ++bc) {ierr = ISDestroy(&bcPoints[bc]);CHKERRQ(ierr);ierr = ISDestroy(&bcComps[bc]);CHKERRQ(ierr);} 7233 ierr = PetscFree3(bcFields,bcPoints,bcComps);CHKERRQ(ierr); 7234 ierr = PetscFree2(numComp,numDof);CHKERRQ(ierr); 7235 ierr = PetscFree(isFE);CHKERRQ(ierr); 7236 PetscFunctionReturn(0); 7237 } 7238 7239 /*@ 7240 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 7241 7242 Input Parameter: 7243 . dm - The DMPlex object 7244 7245 Output Parameter: 7246 . regular - The flag 7247 7248 Level: intermediate 7249 7250 .seealso: DMPlexSetRegularRefinement() 7251 @*/ 7252 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 7253 { 7254 PetscFunctionBegin; 7255 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7256 PetscValidPointer(regular, 2); 7257 *regular = ((DM_Plex *) dm->data)->regularRefinement; 7258 PetscFunctionReturn(0); 7259 } 7260 7261 /*@ 7262 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 7263 7264 Input Parameters: 7265 + dm - The DMPlex object 7266 - regular - The flag 7267 7268 Level: intermediate 7269 7270 .seealso: DMPlexGetRegularRefinement() 7271 @*/ 7272 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 7273 { 7274 PetscFunctionBegin; 7275 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7276 ((DM_Plex *) dm->data)->regularRefinement = regular; 7277 PetscFunctionReturn(0); 7278 } 7279 7280 /* anchors */ 7281 /*@ 7282 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 7283 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 7284 7285 not collective 7286 7287 Input Parameters: 7288 . dm - The DMPlex object 7289 7290 Output Parameters: 7291 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 7292 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 7293 7294 7295 Level: intermediate 7296 7297 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 7298 @*/ 7299 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 7300 { 7301 DM_Plex *plex = (DM_Plex *)dm->data; 7302 PetscErrorCode ierr; 7303 7304 PetscFunctionBegin; 7305 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7306 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 7307 if (anchorSection) *anchorSection = plex->anchorSection; 7308 if (anchorIS) *anchorIS = plex->anchorIS; 7309 PetscFunctionReturn(0); 7310 } 7311 7312 /*@ 7313 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 7314 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 7315 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 7316 7317 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 7318 DMGetConstraints() and filling in the entries in the constraint matrix. 7319 7320 collective on dm 7321 7322 Input Parameters: 7323 + dm - The DMPlex object 7324 . 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). 7325 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 7326 7327 The reference counts of anchorSection and anchorIS are incremented. 7328 7329 Level: intermediate 7330 7331 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 7332 @*/ 7333 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 7334 { 7335 DM_Plex *plex = (DM_Plex *)dm->data; 7336 PetscMPIInt result; 7337 PetscErrorCode ierr; 7338 7339 PetscFunctionBegin; 7340 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7341 if (anchorSection) { 7342 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 7343 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 7344 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 7345 } 7346 if (anchorIS) { 7347 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 7348 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 7349 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 7350 } 7351 7352 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 7353 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 7354 plex->anchorSection = anchorSection; 7355 7356 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 7357 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 7358 plex->anchorIS = anchorIS; 7359 7360 #if defined(PETSC_USE_DEBUG) 7361 if (anchorIS && anchorSection) { 7362 PetscInt size, a, pStart, pEnd; 7363 const PetscInt *anchors; 7364 7365 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 7366 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 7367 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 7368 for (a = 0; a < size; a++) { 7369 PetscInt p; 7370 7371 p = anchors[a]; 7372 if (p >= pStart && p < pEnd) { 7373 PetscInt dof; 7374 7375 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 7376 if (dof) { 7377 PetscErrorCode ierr2; 7378 7379 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 7380 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 7381 } 7382 } 7383 } 7384 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 7385 } 7386 #endif 7387 /* reset the generic constraints */ 7388 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 7389 PetscFunctionReturn(0); 7390 } 7391 7392 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 7393 { 7394 PetscSection anchorSection; 7395 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 7396 PetscErrorCode ierr; 7397 7398 PetscFunctionBegin; 7399 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7400 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 7401 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 7402 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 7403 if (numFields) { 7404 PetscInt f; 7405 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 7406 7407 for (f = 0; f < numFields; f++) { 7408 PetscInt numComp; 7409 7410 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 7411 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 7412 } 7413 } 7414 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 7415 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 7416 pStart = PetscMax(pStart,sStart); 7417 pEnd = PetscMin(pEnd,sEnd); 7418 pEnd = PetscMax(pStart,pEnd); 7419 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 7420 for (p = pStart; p < pEnd; p++) { 7421 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 7422 if (dof) { 7423 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 7424 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 7425 for (f = 0; f < numFields; f++) { 7426 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 7427 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 7428 } 7429 } 7430 } 7431 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 7432 PetscFunctionReturn(0); 7433 } 7434 7435 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 7436 { 7437 PetscSection aSec; 7438 PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 7439 const PetscInt *anchors; 7440 PetscInt numFields, f; 7441 IS aIS; 7442 PetscErrorCode ierr; 7443 7444 PetscFunctionBegin; 7445 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7446 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 7447 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 7448 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 7449 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 7450 ierr = MatSetType(*cMat,MATSEQAIJ);CHKERRQ(ierr); 7451 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 7452 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 7453 /* cSec will be a subset of aSec and section */ 7454 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 7455 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 7456 i[0] = 0; 7457 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 7458 for (p = pStart; p < pEnd; p++) { 7459 PetscInt rDof, rOff, r; 7460 7461 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 7462 if (!rDof) continue; 7463 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 7464 if (numFields) { 7465 for (f = 0; f < numFields; f++) { 7466 annz = 0; 7467 for (r = 0; r < rDof; r++) { 7468 a = anchors[rOff + r]; 7469 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 7470 annz += aDof; 7471 } 7472 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 7473 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 7474 for (q = 0; q < dof; q++) { 7475 i[off + q + 1] = i[off + q] + annz; 7476 } 7477 } 7478 } 7479 else { 7480 annz = 0; 7481 for (q = 0; q < dof; q++) { 7482 a = anchors[off + q]; 7483 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 7484 annz += aDof; 7485 } 7486 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 7487 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 7488 for (q = 0; q < dof; q++) { 7489 i[off + q + 1] = i[off + q] + annz; 7490 } 7491 } 7492 } 7493 nnz = i[m]; 7494 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 7495 offset = 0; 7496 for (p = pStart; p < pEnd; p++) { 7497 if (numFields) { 7498 for (f = 0; f < numFields; f++) { 7499 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 7500 for (q = 0; q < dof; q++) { 7501 PetscInt rDof, rOff, r; 7502 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 7503 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 7504 for (r = 0; r < rDof; r++) { 7505 PetscInt s; 7506 7507 a = anchors[rOff + r]; 7508 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 7509 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 7510 for (s = 0; s < aDof; s++) { 7511 j[offset++] = aOff + s; 7512 } 7513 } 7514 } 7515 } 7516 } 7517 else { 7518 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 7519 for (q = 0; q < dof; q++) { 7520 PetscInt rDof, rOff, r; 7521 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 7522 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 7523 for (r = 0; r < rDof; r++) { 7524 PetscInt s; 7525 7526 a = anchors[rOff + r]; 7527 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 7528 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 7529 for (s = 0; s < aDof; s++) { 7530 j[offset++] = aOff + s; 7531 } 7532 } 7533 } 7534 } 7535 } 7536 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 7537 ierr = PetscFree(i);CHKERRQ(ierr); 7538 ierr = PetscFree(j);CHKERRQ(ierr); 7539 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7540 PetscFunctionReturn(0); 7541 } 7542 7543 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 7544 { 7545 DM_Plex *plex = (DM_Plex *)dm->data; 7546 PetscSection anchorSection, section, cSec; 7547 Mat cMat; 7548 PetscErrorCode ierr; 7549 7550 PetscFunctionBegin; 7551 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7552 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 7553 if (anchorSection) { 7554 PetscDS ds; 7555 PetscInt nf; 7556 7557 ierr = DMGetSection(dm,§ion);CHKERRQ(ierr); 7558 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 7559 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 7560 ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 7561 ierr = PetscDSGetNumFields(ds,&nf);CHKERRQ(ierr); 7562 if (nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 7563 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 7564 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 7565 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 7566 } 7567 PetscFunctionReturn(0); 7568 } 7569 7570 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 7571 { 7572 PetscDS prob; 7573 IS subis; 7574 PetscSection section, subsection; 7575 PetscErrorCode ierr; 7576 7577 PetscFunctionBegin; 7578 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7579 if (!section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 7580 if (!subdm) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 7581 /* Create subdomain */ 7582 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 7583 /* Create submodel */ 7584 ierr = DMPlexCreateSubpointIS(*subdm, &subis);CHKERRQ(ierr); 7585 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 7586 ierr = ISDestroy(&subis);CHKERRQ(ierr); 7587 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 7588 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 7589 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 7590 ierr = DMSetDS(*subdm, prob);CHKERRQ(ierr); 7591 /* Create map from submodel to global model */ 7592 if (is) { 7593 PetscSection sectionGlobal, subsectionGlobal; 7594 IS spIS; 7595 const PetscInt *spmap; 7596 PetscInt *subIndices; 7597 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 7598 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 7599 7600 ierr = DMPlexCreateSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 7601 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 7602 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 7603 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 7604 ierr = DMGetDefaultGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 7605 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 7606 for (p = pStart; p < pEnd; ++p) { 7607 PetscInt gdof, pSubSize = 0; 7608 7609 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 7610 if (gdof > 0) { 7611 for (f = 0; f < Nf; ++f) { 7612 PetscInt fdof, fcdof; 7613 7614 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 7615 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 7616 pSubSize += fdof-fcdof; 7617 } 7618 subSize += pSubSize; 7619 if (pSubSize) { 7620 if (bs < 0) { 7621 bs = pSubSize; 7622 } else if (bs != pSubSize) { 7623 /* Layout does not admit a pointwise block size */ 7624 bs = 1; 7625 } 7626 } 7627 } 7628 } 7629 /* Must have same blocksize on all procs (some might have no points) */ 7630 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 7631 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 7632 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 7633 else {bs = bsMinMax[0];} 7634 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 7635 for (p = pStart; p < pEnd; ++p) { 7636 PetscInt gdof, goff; 7637 7638 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 7639 if (gdof > 0) { 7640 const PetscInt point = spmap[p]; 7641 7642 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 7643 for (f = 0; f < Nf; ++f) { 7644 PetscInt fdof, fcdof, fc, f2, poff = 0; 7645 7646 /* Can get rid of this loop by storing field information in the global section */ 7647 for (f2 = 0; f2 < f; ++f2) { 7648 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 7649 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 7650 poff += fdof-fcdof; 7651 } 7652 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7653 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7654 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 7655 subIndices[subOff] = goff+poff+fc; 7656 } 7657 } 7658 } 7659 } 7660 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 7661 ierr = ISDestroy(&spIS);CHKERRQ(ierr); 7662 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 7663 if (bs > 1) { 7664 /* We need to check that the block size does not come from non-contiguous fields */ 7665 PetscInt i, j, set = 1; 7666 for (i = 0; i < subSize; i += bs) { 7667 for (j = 0; j < bs; ++j) { 7668 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 7669 } 7670 } 7671 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 7672 } 7673 /* Attach nullspace */ 7674 for (f = 0; f < Nf; ++f) { 7675 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 7676 if ((*subdm)->nullspaceConstructors[f]) break; 7677 } 7678 if (f < Nf) { 7679 MatNullSpace nullSpace; 7680 7681 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, &nullSpace);CHKERRQ(ierr); 7682 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 7683 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 7684 } 7685 } 7686 PetscFunctionReturn(0); 7687 } 7688