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