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