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