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