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