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