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