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