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 3555 DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 3556 lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 3557 section provided (or default section of the DM). 3558 3559 Input Parameters: 3560 + dm - The DM 3561 . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 3562 - section - The PetscSection to reorder, or NULL for the default section 3563 3564 Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 3565 degree of the basis. 3566 3567 Example: 3568 A typical interpolated single-quad mesh might order points as 3569 .vb 3570 [c0, v1, v2, v3, v4, e5, e6, e7, e8] 3571 3572 v4 -- e6 -- v3 3573 | | 3574 e7 c0 e8 3575 | | 3576 v1 -- e5 -- v2 3577 .ve 3578 3579 (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 3580 dofs in the order of points, e.g., 3581 .vb 3582 c0 -> [0,1,2,3] 3583 v1 -> [4] 3584 ... 3585 e5 -> [8, 9] 3586 .ve 3587 3588 which corresponds to the dofs 3589 .vb 3590 6 10 11 7 3591 13 2 3 15 3592 12 0 1 14 3593 4 8 9 5 3594 .ve 3595 3596 The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 3597 .vb 3598 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 3599 .ve 3600 3601 After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 3602 .vb 3603 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 3604 .ve 3605 3606 Level: developer 3607 3608 .seealso: DMGetSection(), PetscSectionSetClosurePermutation() 3609 @*/ 3610 PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 3611 { 3612 DMLabel label; 3613 PetscInt *perm; 3614 PetscInt dim, depth, eStart, k, Nf, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 3615 PetscErrorCode ierr; 3616 3617 PetscFunctionBegin; 3618 if (point < 0) {ierr = DMPlexGetDepthStratum(dm, 1, &point, NULL);CHKERRQ(ierr);} 3619 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3620 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3621 ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); 3622 if (depth == 1) {eStart = point;} 3623 else if (depth == dim) { 3624 const PetscInt *cone; 3625 3626 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3627 if (dim == 2) eStart = cone[0]; 3628 else if (dim == 3) { 3629 const PetscInt *cone2; 3630 ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 3631 eStart = cone2[0]; 3632 } 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); 3633 } 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); 3634 if (!section) {ierr = DMGetSection(dm, §ion);CHKERRQ(ierr);} 3635 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 3636 if (dim < 1) PetscFunctionReturn(0); 3637 for (f = 0; f < Nf; ++f) { 3638 /* An order k SEM disc has k-1 dofs on an edge */ 3639 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3640 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3641 k = k/Nc + 1; 3642 size += PetscPowInt(k+1, dim)*Nc; 3643 } 3644 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 3645 for (f = 0; f < Nf; ++f) { 3646 switch (dim) { 3647 case 1: 3648 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3649 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3650 k = k/Nc + 1; 3651 /* 3652 Original ordering is [ edge of length k-1; vtx0; vtx1 ] 3653 We want [ vtx0; edge of length k-1; vtx1 ] 3654 */ 3655 for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 3656 for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 3657 for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 3658 foffset = offset; 3659 break; 3660 case 2: 3661 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 3662 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3663 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3664 k = k/Nc + 1; 3665 /* The SEM order is 3666 3667 v_lb, {e_b}, v_rb, 3668 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 3669 v_lt, reverse {e_t}, v_rt 3670 */ 3671 { 3672 const PetscInt of = 0; 3673 const PetscInt oeb = of + PetscSqr(k-1); 3674 const PetscInt oer = oeb + (k-1); 3675 const PetscInt oet = oer + (k-1); 3676 const PetscInt oel = oet + (k-1); 3677 const PetscInt ovlb = oel + (k-1); 3678 const PetscInt ovrb = ovlb + 1; 3679 const PetscInt ovrt = ovrb + 1; 3680 const PetscInt ovlt = ovrt + 1; 3681 PetscInt o; 3682 3683 /* bottom */ 3684 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 3685 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3686 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 3687 /* middle */ 3688 for (i = 0; i < k-1; ++i) { 3689 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 3690 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; 3691 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 3692 } 3693 /* top */ 3694 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 3695 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3696 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 3697 foffset = offset; 3698 } 3699 break; 3700 case 3: 3701 /* The original hex closure is 3702 3703 {c, 3704 f_b, f_t, f_f, f_b, f_r, f_l, 3705 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 3706 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 3707 */ 3708 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3709 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3710 k = k/Nc + 1; 3711 /* The SEM order is 3712 Bottom Slice 3713 v_blf, {e^{(k-1)-n}_bf}, v_brf, 3714 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 3715 v_blb, {e_bb}, v_brb, 3716 3717 Middle Slice (j) 3718 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 3719 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 3720 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 3721 3722 Top Slice 3723 v_tlf, {e_tf}, v_trf, 3724 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 3725 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 3726 */ 3727 { 3728 const PetscInt oc = 0; 3729 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 3730 const PetscInt oft = ofb + PetscSqr(k-1); 3731 const PetscInt off = oft + PetscSqr(k-1); 3732 const PetscInt ofk = off + PetscSqr(k-1); 3733 const PetscInt ofr = ofk + PetscSqr(k-1); 3734 const PetscInt ofl = ofr + PetscSqr(k-1); 3735 const PetscInt oebl = ofl + PetscSqr(k-1); 3736 const PetscInt oebb = oebl + (k-1); 3737 const PetscInt oebr = oebb + (k-1); 3738 const PetscInt oebf = oebr + (k-1); 3739 const PetscInt oetf = oebf + (k-1); 3740 const PetscInt oetr = oetf + (k-1); 3741 const PetscInt oetb = oetr + (k-1); 3742 const PetscInt oetl = oetb + (k-1); 3743 const PetscInt oerf = oetl + (k-1); 3744 const PetscInt oelf = oerf + (k-1); 3745 const PetscInt oelb = oelf + (k-1); 3746 const PetscInt oerb = oelb + (k-1); 3747 const PetscInt ovblf = oerb + (k-1); 3748 const PetscInt ovblb = ovblf + 1; 3749 const PetscInt ovbrb = ovblb + 1; 3750 const PetscInt ovbrf = ovbrb + 1; 3751 const PetscInt ovtlf = ovbrf + 1; 3752 const PetscInt ovtrf = ovtlf + 1; 3753 const PetscInt ovtrb = ovtrf + 1; 3754 const PetscInt ovtlb = ovtrb + 1; 3755 PetscInt o, n; 3756 3757 /* Bottom Slice */ 3758 /* bottom */ 3759 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 3760 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3761 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 3762 /* middle */ 3763 for (i = 0; i < k-1; ++i) { 3764 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 3765 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;} 3766 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 3767 } 3768 /* top */ 3769 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 3770 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3771 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 3772 3773 /* Middle Slice */ 3774 for (j = 0; j < k-1; ++j) { 3775 /* bottom */ 3776 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 3777 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; 3778 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 3779 /* middle */ 3780 for (i = 0; i < k-1; ++i) { 3781 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 3782 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; 3783 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 3784 } 3785 /* top */ 3786 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 3787 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; 3788 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 3789 } 3790 3791 /* Top Slice */ 3792 /* bottom */ 3793 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 3794 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3795 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 3796 /* middle */ 3797 for (i = 0; i < k-1; ++i) { 3798 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 3799 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 3800 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 3801 } 3802 /* top */ 3803 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 3804 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3805 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 3806 3807 foffset = offset; 3808 } 3809 break; 3810 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", dim); 3811 } 3812 } 3813 if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 3814 /* Check permutation */ 3815 { 3816 PetscInt *check; 3817 3818 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 3819 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]);} 3820 for (i = 0; i < size; ++i) check[perm[i]] = i; 3821 for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 3822 ierr = PetscFree(check);CHKERRQ(ierr); 3823 } 3824 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 3825 PetscFunctionReturn(0); 3826 } 3827 3828 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 3829 { 3830 PetscDS prob; 3831 PetscInt depth, Nf, h; 3832 DMLabel label; 3833 PetscErrorCode ierr; 3834 3835 PetscFunctionBeginHot; 3836 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 3837 Nf = prob->Nf; 3838 label = dm->depthLabel; 3839 *dspace = NULL; 3840 if (field < Nf) { 3841 PetscObject disc = prob->disc[field]; 3842 3843 if (disc->classid == PETSCFE_CLASSID) { 3844 PetscDualSpace dsp; 3845 3846 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 3847 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 3848 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 3849 h = depth - 1 - h; 3850 if (h) { 3851 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 3852 } else { 3853 *dspace = dsp; 3854 } 3855 } 3856 } 3857 PetscFunctionReturn(0); 3858 } 3859 3860 3861 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3862 { 3863 PetscScalar *array, *vArray; 3864 const PetscInt *cone, *coneO; 3865 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 3866 PetscErrorCode ierr; 3867 3868 PetscFunctionBeginHot; 3869 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3870 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3871 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3872 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3873 if (!values || !*values) { 3874 if ((point >= pStart) && (point < pEnd)) { 3875 PetscInt dof; 3876 3877 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3878 size += dof; 3879 } 3880 for (p = 0; p < numPoints; ++p) { 3881 const PetscInt cp = cone[p]; 3882 PetscInt dof; 3883 3884 if ((cp < pStart) || (cp >= pEnd)) continue; 3885 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3886 size += dof; 3887 } 3888 if (!values) { 3889 if (csize) *csize = size; 3890 PetscFunctionReturn(0); 3891 } 3892 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 3893 } else { 3894 array = *values; 3895 } 3896 size = 0; 3897 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3898 if ((point >= pStart) && (point < pEnd)) { 3899 PetscInt dof, off, d; 3900 PetscScalar *varr; 3901 3902 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3903 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3904 varr = &vArray[off]; 3905 for (d = 0; d < dof; ++d, ++offset) { 3906 array[offset] = varr[d]; 3907 } 3908 size += dof; 3909 } 3910 for (p = 0; p < numPoints; ++p) { 3911 const PetscInt cp = cone[p]; 3912 PetscInt o = coneO[p]; 3913 PetscInt dof, off, d; 3914 PetscScalar *varr; 3915 3916 if ((cp < pStart) || (cp >= pEnd)) continue; 3917 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3918 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 3919 varr = &vArray[off]; 3920 if (o >= 0) { 3921 for (d = 0; d < dof; ++d, ++offset) { 3922 array[offset] = varr[d]; 3923 } 3924 } else { 3925 for (d = dof-1; d >= 0; --d, ++offset) { 3926 array[offset] = varr[d]; 3927 } 3928 } 3929 size += dof; 3930 } 3931 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3932 if (!*values) { 3933 if (csize) *csize = size; 3934 *values = array; 3935 } else { 3936 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 3937 *csize = size; 3938 } 3939 PetscFunctionReturn(0); 3940 } 3941 3942 static PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 3943 { 3944 const PetscInt *cla; 3945 PetscInt np, *pts = NULL; 3946 PetscErrorCode ierr; 3947 3948 PetscFunctionBeginHot; 3949 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 3950 if (!*clPoints) { 3951 PetscInt pStart, pEnd, p, q; 3952 3953 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3954 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 3955 /* Compress out points not in the section */ 3956 for (p = 0, q = 0; p < np; p++) { 3957 PetscInt r = pts[2*p]; 3958 if ((r >= pStart) && (r < pEnd)) { 3959 pts[q*2] = r; 3960 pts[q*2+1] = pts[2*p+1]; 3961 ++q; 3962 } 3963 } 3964 np = q; 3965 cla = NULL; 3966 } else { 3967 PetscInt dof, off; 3968 3969 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 3970 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 3971 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 3972 np = dof/2; 3973 pts = (PetscInt *) &cla[off]; 3974 } 3975 *numPoints = np; 3976 *points = pts; 3977 *clp = cla; 3978 3979 PetscFunctionReturn(0); 3980 } 3981 3982 static PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 3983 { 3984 PetscErrorCode ierr; 3985 3986 PetscFunctionBeginHot; 3987 if (!*clPoints) { 3988 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 3989 } else { 3990 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 3991 } 3992 *numPoints = 0; 3993 *points = NULL; 3994 *clSec = NULL; 3995 *clPoints = NULL; 3996 *clp = NULL; 3997 PetscFunctionReturn(0); 3998 } 3999 4000 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[]) 4001 { 4002 PetscInt offset = 0, p; 4003 const PetscInt **perms = NULL; 4004 const PetscScalar **flips = NULL; 4005 PetscErrorCode ierr; 4006 4007 PetscFunctionBeginHot; 4008 *size = 0; 4009 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4010 for (p = 0; p < numPoints; p++) { 4011 const PetscInt point = points[2*p]; 4012 const PetscInt *perm = perms ? perms[p] : NULL; 4013 const PetscScalar *flip = flips ? flips[p] : NULL; 4014 PetscInt dof, off, d; 4015 const PetscScalar *varr; 4016 4017 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4018 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4019 varr = &vArray[off]; 4020 if (clperm) { 4021 if (perm) { 4022 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 4023 } else { 4024 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 4025 } 4026 if (flip) { 4027 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 4028 } 4029 } else { 4030 if (perm) { 4031 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 4032 } else { 4033 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 4034 } 4035 if (flip) { 4036 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 4037 } 4038 } 4039 offset += dof; 4040 } 4041 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4042 *size = offset; 4043 PetscFunctionReturn(0); 4044 } 4045 4046 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[]) 4047 { 4048 PetscInt offset = 0, f; 4049 PetscErrorCode ierr; 4050 4051 PetscFunctionBeginHot; 4052 *size = 0; 4053 for (f = 0; f < numFields; ++f) { 4054 PetscInt p; 4055 const PetscInt **perms = NULL; 4056 const PetscScalar **flips = NULL; 4057 4058 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4059 for (p = 0; p < numPoints; p++) { 4060 const PetscInt point = points[2*p]; 4061 PetscInt fdof, foff, b; 4062 const PetscScalar *varr; 4063 const PetscInt *perm = perms ? perms[p] : NULL; 4064 const PetscScalar *flip = flips ? flips[p] : NULL; 4065 4066 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4067 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4068 varr = &vArray[foff]; 4069 if (clperm) { 4070 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 4071 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 4072 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 4073 } else { 4074 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 4075 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 4076 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 4077 } 4078 offset += fdof; 4079 } 4080 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4081 } 4082 *size = offset; 4083 PetscFunctionReturn(0); 4084 } 4085 4086 /*@C 4087 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 4088 4089 Not collective 4090 4091 Input Parameters: 4092 + dm - The DM 4093 . section - The section describing the layout in v, or NULL to use the default section 4094 . v - The local vector 4095 . point - The point in the DM 4096 . csize - The size of the input values array, or NULL 4097 - values - An array to use for the values, or NULL to have it allocated automatically 4098 4099 Output Parameters: 4100 + csize - The number of values in the closure 4101 - values - The array of values. If the user provided NULL, it is a borrowed array and should not be freed 4102 4103 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 4104 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 4105 $ assembly function, and a user may already have allocated storage for this operation. 4106 $ 4107 $ A typical use could be 4108 $ 4109 $ values = NULL; 4110 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4111 $ for (cl = 0; cl < clSize; ++cl) { 4112 $ <Compute on closure> 4113 $ } 4114 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4115 $ 4116 $ or 4117 $ 4118 $ PetscMalloc1(clMaxSize, &values); 4119 $ for (p = pStart; p < pEnd; ++p) { 4120 $ clSize = clMaxSize; 4121 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4122 $ for (cl = 0; cl < clSize; ++cl) { 4123 $ <Compute on closure> 4124 $ } 4125 $ } 4126 $ PetscFree(values); 4127 4128 Fortran Notes: 4129 Since it returns an array, this routine is only available in Fortran 90, and you must 4130 include petsc.h90 in your code. 4131 4132 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4133 4134 Level: intermediate 4135 4136 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4137 @*/ 4138 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4139 { 4140 PetscSection clSection; 4141 IS clPoints; 4142 PetscScalar *array; 4143 const PetscScalar *vArray; 4144 PetscInt *points = NULL; 4145 const PetscInt *clp, *perm; 4146 PetscInt depth, numFields, numPoints, size; 4147 PetscErrorCode ierr; 4148 4149 PetscFunctionBeginHot; 4150 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4151 if (!section) {ierr = DMGetSection(dm, §ion);CHKERRQ(ierr);} 4152 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4153 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4154 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4155 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4156 if (depth == 1 && numFields < 2) { 4157 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 4158 PetscFunctionReturn(0); 4159 } 4160 /* Get points */ 4161 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4162 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &perm);CHKERRQ(ierr); 4163 /* Get array */ 4164 if (!values || !*values) { 4165 PetscInt asize = 0, dof, p; 4166 4167 for (p = 0; p < numPoints*2; p += 2) { 4168 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4169 asize += dof; 4170 } 4171 if (!values) { 4172 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4173 if (csize) *csize = asize; 4174 PetscFunctionReturn(0); 4175 } 4176 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 4177 } else { 4178 array = *values; 4179 } 4180 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 4181 /* Get values */ 4182 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 4183 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, array);CHKERRQ(ierr);} 4184 /* Cleanup points */ 4185 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4186 /* Cleanup array */ 4187 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 4188 if (!*values) { 4189 if (csize) *csize = size; 4190 *values = array; 4191 } else { 4192 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 4193 *csize = size; 4194 } 4195 PetscFunctionReturn(0); 4196 } 4197 4198 /*@C 4199 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 4200 4201 Not collective 4202 4203 Input Parameters: 4204 + dm - The DM 4205 . section - The section describing the layout in v, or NULL to use the default section 4206 . v - The local vector 4207 . point - The point in the DM 4208 . csize - The number of values in the closure, or NULL 4209 - values - The array of values, which is a borrowed array and should not be freed 4210 4211 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 4212 4213 Fortran Notes: 4214 Since it returns an array, this routine is only available in Fortran 90, and you must 4215 include petsc.h90 in your code. 4216 4217 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4218 4219 Level: intermediate 4220 4221 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4222 @*/ 4223 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4224 { 4225 PetscInt size = 0; 4226 PetscErrorCode ierr; 4227 4228 PetscFunctionBegin; 4229 /* Should work without recalculating size */ 4230 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 4231 *values = NULL; 4232 PetscFunctionReturn(0); 4233 } 4234 4235 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 4236 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 4237 4238 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[]) 4239 { 4240 PetscInt cdof; /* The number of constraints on this point */ 4241 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4242 PetscScalar *a; 4243 PetscInt off, cind = 0, k; 4244 PetscErrorCode ierr; 4245 4246 PetscFunctionBegin; 4247 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4248 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4249 a = &array[off]; 4250 if (!cdof || setBC) { 4251 if (clperm) { 4252 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 4253 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 4254 } else { 4255 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 4256 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 4257 } 4258 } else { 4259 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4260 if (clperm) { 4261 if (perm) {for (k = 0; k < dof; ++k) { 4262 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4263 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 4264 } 4265 } else { 4266 for (k = 0; k < dof; ++k) { 4267 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4268 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 4269 } 4270 } 4271 } else { 4272 if (perm) { 4273 for (k = 0; k < dof; ++k) { 4274 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4275 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 4276 } 4277 } else { 4278 for (k = 0; k < dof; ++k) { 4279 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4280 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 4281 } 4282 } 4283 } 4284 } 4285 PetscFunctionReturn(0); 4286 } 4287 4288 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[]) 4289 { 4290 PetscInt cdof; /* The number of constraints on this point */ 4291 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4292 PetscScalar *a; 4293 PetscInt off, cind = 0, k; 4294 PetscErrorCode ierr; 4295 4296 PetscFunctionBegin; 4297 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4298 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4299 a = &array[off]; 4300 if (cdof) { 4301 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4302 if (clperm) { 4303 if (perm) { 4304 for (k = 0; k < dof; ++k) { 4305 if ((cind < cdof) && (k == cdofs[cind])) { 4306 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 4307 cind++; 4308 } 4309 } 4310 } else { 4311 for (k = 0; k < dof; ++k) { 4312 if ((cind < cdof) && (k == cdofs[cind])) { 4313 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 4314 cind++; 4315 } 4316 } 4317 } 4318 } else { 4319 if (perm) { 4320 for (k = 0; k < dof; ++k) { 4321 if ((cind < cdof) && (k == cdofs[cind])) { 4322 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 4323 cind++; 4324 } 4325 } 4326 } else { 4327 for (k = 0; k < dof; ++k) { 4328 if ((cind < cdof) && (k == cdofs[cind])) { 4329 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 4330 cind++; 4331 } 4332 } 4333 } 4334 } 4335 } 4336 PetscFunctionReturn(0); 4337 } 4338 4339 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[]) 4340 { 4341 PetscScalar *a; 4342 PetscInt fdof, foff, fcdof, foffset = *offset; 4343 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4344 PetscInt cind = 0, b; 4345 PetscErrorCode ierr; 4346 4347 PetscFunctionBegin; 4348 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4349 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 4350 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4351 a = &array[foff]; 4352 if (!fcdof || setBC) { 4353 if (clperm) { 4354 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 4355 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 4356 } else { 4357 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 4358 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 4359 } 4360 } else { 4361 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4362 if (clperm) { 4363 if (perm) { 4364 for (b = 0; b < fdof; b++) { 4365 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4366 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 4367 } 4368 } else { 4369 for (b = 0; b < fdof; b++) { 4370 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4371 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 4372 } 4373 } 4374 } else { 4375 if (perm) { 4376 for (b = 0; b < fdof; b++) { 4377 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4378 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 4379 } 4380 } else { 4381 for (b = 0; b < fdof; b++) { 4382 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4383 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 4384 } 4385 } 4386 } 4387 } 4388 *offset += fdof; 4389 PetscFunctionReturn(0); 4390 } 4391 4392 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[]) 4393 { 4394 PetscScalar *a; 4395 PetscInt fdof, foff, fcdof, foffset = *offset; 4396 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4397 PetscInt cind = 0, ncind = 0, b; 4398 PetscBool ncSet, fcSet; 4399 PetscErrorCode ierr; 4400 4401 PetscFunctionBegin; 4402 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4403 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 4404 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4405 a = &array[foff]; 4406 if (fcdof) { 4407 /* We just override fcdof and fcdofs with Ncc and comps */ 4408 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4409 if (clperm) { 4410 if (perm) { 4411 if (comps) { 4412 for (b = 0; b < fdof; b++) { 4413 ncSet = fcSet = PETSC_FALSE; 4414 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4415 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4416 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 4417 } 4418 } else { 4419 for (b = 0; b < fdof; b++) { 4420 if ((cind < fcdof) && (b == fcdofs[cind])) { 4421 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 4422 ++cind; 4423 } 4424 } 4425 } 4426 } else { 4427 if (comps) { 4428 for (b = 0; b < fdof; b++) { 4429 ncSet = fcSet = PETSC_FALSE; 4430 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4431 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4432 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 4433 } 4434 } else { 4435 for (b = 0; b < fdof; b++) { 4436 if ((cind < fcdof) && (b == fcdofs[cind])) { 4437 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 4438 ++cind; 4439 } 4440 } 4441 } 4442 } 4443 } else { 4444 if (perm) { 4445 if (comps) { 4446 for (b = 0; b < fdof; b++) { 4447 ncSet = fcSet = PETSC_FALSE; 4448 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4449 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4450 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 4451 } 4452 } else { 4453 for (b = 0; b < fdof; b++) { 4454 if ((cind < fcdof) && (b == fcdofs[cind])) { 4455 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 4456 ++cind; 4457 } 4458 } 4459 } 4460 } else { 4461 if (comps) { 4462 for (b = 0; b < fdof; b++) { 4463 ncSet = fcSet = PETSC_FALSE; 4464 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4465 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4466 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 4467 } 4468 } else { 4469 for (b = 0; b < fdof; b++) { 4470 if ((cind < fcdof) && (b == fcdofs[cind])) { 4471 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 4472 ++cind; 4473 } 4474 } 4475 } 4476 } 4477 } 4478 } 4479 *offset += fdof; 4480 PetscFunctionReturn(0); 4481 } 4482 4483 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4484 { 4485 PetscScalar *array; 4486 const PetscInt *cone, *coneO; 4487 PetscInt pStart, pEnd, p, numPoints, off, dof; 4488 PetscErrorCode ierr; 4489 4490 PetscFunctionBeginHot; 4491 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4492 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 4493 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4494 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 4495 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4496 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 4497 const PetscInt cp = !p ? point : cone[p-1]; 4498 const PetscInt o = !p ? 0 : coneO[p-1]; 4499 4500 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 4501 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4502 /* ADD_VALUES */ 4503 { 4504 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4505 PetscScalar *a; 4506 PetscInt cdof, coff, cind = 0, k; 4507 4508 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 4509 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 4510 a = &array[coff]; 4511 if (!cdof) { 4512 if (o >= 0) { 4513 for (k = 0; k < dof; ++k) { 4514 a[k] += values[off+k]; 4515 } 4516 } else { 4517 for (k = 0; k < dof; ++k) { 4518 a[k] += values[off+dof-k-1]; 4519 } 4520 } 4521 } else { 4522 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 4523 if (o >= 0) { 4524 for (k = 0; k < dof; ++k) { 4525 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4526 a[k] += values[off+k]; 4527 } 4528 } else { 4529 for (k = 0; k < dof; ++k) { 4530 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4531 a[k] += values[off+dof-k-1]; 4532 } 4533 } 4534 } 4535 } 4536 } 4537 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4538 PetscFunctionReturn(0); 4539 } 4540 4541 /*@C 4542 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 4543 4544 Not collective 4545 4546 Input Parameters: 4547 + dm - The DM 4548 . section - The section describing the layout in v, or NULL to use the default section 4549 . v - The local vector 4550 . point - The point in the DM 4551 . values - The array of values 4552 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 4553 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 4554 4555 Fortran Notes: 4556 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4557 4558 Level: intermediate 4559 4560 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 4561 @*/ 4562 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4563 { 4564 PetscSection clSection; 4565 IS clPoints; 4566 PetscScalar *array; 4567 PetscInt *points = NULL; 4568 const PetscInt *clp, *clperm; 4569 PetscInt depth, numFields, numPoints, p; 4570 PetscErrorCode ierr; 4571 4572 PetscFunctionBeginHot; 4573 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4574 if (!section) {ierr = DMGetSection(dm, §ion);CHKERRQ(ierr);} 4575 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4576 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4577 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4578 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4579 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 4580 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 4581 PetscFunctionReturn(0); 4582 } 4583 /* Get points */ 4584 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 4585 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4586 /* Get array */ 4587 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4588 /* Get values */ 4589 if (numFields > 0) { 4590 PetscInt offset = 0, f; 4591 for (f = 0; f < numFields; ++f) { 4592 const PetscInt **perms = NULL; 4593 const PetscScalar **flips = NULL; 4594 4595 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4596 switch (mode) { 4597 case INSERT_VALUES: 4598 for (p = 0; p < numPoints; p++) { 4599 const PetscInt point = points[2*p]; 4600 const PetscInt *perm = perms ? perms[p] : NULL; 4601 const PetscScalar *flip = flips ? flips[p] : NULL; 4602 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 4603 } break; 4604 case INSERT_ALL_VALUES: 4605 for (p = 0; p < numPoints; p++) { 4606 const PetscInt point = points[2*p]; 4607 const PetscInt *perm = perms ? perms[p] : NULL; 4608 const PetscScalar *flip = flips ? flips[p] : NULL; 4609 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 4610 } break; 4611 case INSERT_BC_VALUES: 4612 for (p = 0; p < numPoints; p++) { 4613 const PetscInt point = points[2*p]; 4614 const PetscInt *perm = perms ? perms[p] : NULL; 4615 const PetscScalar *flip = flips ? flips[p] : NULL; 4616 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 4617 } break; 4618 case ADD_VALUES: 4619 for (p = 0; p < numPoints; p++) { 4620 const PetscInt point = points[2*p]; 4621 const PetscInt *perm = perms ? perms[p] : NULL; 4622 const PetscScalar *flip = flips ? flips[p] : NULL; 4623 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 4624 } break; 4625 case ADD_ALL_VALUES: 4626 for (p = 0; p < numPoints; p++) { 4627 const PetscInt point = points[2*p]; 4628 const PetscInt *perm = perms ? perms[p] : NULL; 4629 const PetscScalar *flip = flips ? flips[p] : NULL; 4630 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 4631 } break; 4632 case ADD_BC_VALUES: 4633 for (p = 0; p < numPoints; p++) { 4634 const PetscInt point = points[2*p]; 4635 const PetscInt *perm = perms ? perms[p] : NULL; 4636 const PetscScalar *flip = flips ? flips[p] : NULL; 4637 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 4638 } break; 4639 default: 4640 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4641 } 4642 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4643 } 4644 } else { 4645 PetscInt dof, off; 4646 const PetscInt **perms = NULL; 4647 const PetscScalar **flips = NULL; 4648 4649 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4650 switch (mode) { 4651 case INSERT_VALUES: 4652 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4653 const PetscInt point = points[2*p]; 4654 const PetscInt *perm = perms ? perms[p] : NULL; 4655 const PetscScalar *flip = flips ? flips[p] : NULL; 4656 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4657 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 4658 } break; 4659 case INSERT_ALL_VALUES: 4660 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4661 const PetscInt point = points[2*p]; 4662 const PetscInt *perm = perms ? perms[p] : NULL; 4663 const PetscScalar *flip = flips ? flips[p] : NULL; 4664 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4665 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 4666 } break; 4667 case INSERT_BC_VALUES: 4668 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4669 const PetscInt point = points[2*p]; 4670 const PetscInt *perm = perms ? perms[p] : NULL; 4671 const PetscScalar *flip = flips ? flips[p] : NULL; 4672 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4673 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 4674 } break; 4675 case ADD_VALUES: 4676 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4677 const PetscInt point = points[2*p]; 4678 const PetscInt *perm = perms ? perms[p] : NULL; 4679 const PetscScalar *flip = flips ? flips[p] : NULL; 4680 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4681 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 4682 } break; 4683 case ADD_ALL_VALUES: 4684 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4685 const PetscInt point = points[2*p]; 4686 const PetscInt *perm = perms ? perms[p] : NULL; 4687 const PetscScalar *flip = flips ? flips[p] : NULL; 4688 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4689 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 4690 } break; 4691 case ADD_BC_VALUES: 4692 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4693 const PetscInt point = points[2*p]; 4694 const PetscInt *perm = perms ? perms[p] : NULL; 4695 const PetscScalar *flip = flips ? flips[p] : NULL; 4696 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4697 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 4698 } break; 4699 default: 4700 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4701 } 4702 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4703 } 4704 /* Cleanup points */ 4705 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4706 /* Cleanup array */ 4707 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4708 PetscFunctionReturn(0); 4709 } 4710 4711 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, PetscInt Ncc, const PetscInt comps[], const PetscScalar values[], InsertMode mode) 4712 { 4713 PetscSection clSection; 4714 IS clPoints; 4715 PetscScalar *array; 4716 PetscInt *points = NULL; 4717 const PetscInt *clp, *clperm; 4718 PetscInt numFields, numPoints, p; 4719 PetscInt offset = 0, f; 4720 PetscErrorCode ierr; 4721 4722 PetscFunctionBeginHot; 4723 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4724 if (!section) {ierr = DMGetSection(dm, §ion);CHKERRQ(ierr);} 4725 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4726 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4727 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4728 /* Get points */ 4729 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 4730 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4731 /* Get array */ 4732 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4733 /* Get values */ 4734 for (f = 0; f < numFields; ++f) { 4735 const PetscInt **perms = NULL; 4736 const PetscScalar **flips = NULL; 4737 4738 if (!fieldActive[f]) { 4739 for (p = 0; p < numPoints*2; p += 2) { 4740 PetscInt fdof; 4741 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4742 offset += fdof; 4743 } 4744 continue; 4745 } 4746 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4747 switch (mode) { 4748 case INSERT_VALUES: 4749 for (p = 0; p < numPoints; p++) { 4750 const PetscInt point = points[2*p]; 4751 const PetscInt *perm = perms ? perms[p] : NULL; 4752 const PetscScalar *flip = flips ? flips[p] : NULL; 4753 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 4754 } break; 4755 case INSERT_ALL_VALUES: 4756 for (p = 0; p < numPoints; p++) { 4757 const PetscInt point = points[2*p]; 4758 const PetscInt *perm = perms ? perms[p] : NULL; 4759 const PetscScalar *flip = flips ? flips[p] : NULL; 4760 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 4761 } break; 4762 case INSERT_BC_VALUES: 4763 for (p = 0; p < numPoints; p++) { 4764 const PetscInt point = points[2*p]; 4765 const PetscInt *perm = perms ? perms[p] : NULL; 4766 const PetscScalar *flip = flips ? flips[p] : NULL; 4767 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, clperm, values, &offset, array); 4768 } break; 4769 case ADD_VALUES: 4770 for (p = 0; p < numPoints; p++) { 4771 const PetscInt point = points[2*p]; 4772 const PetscInt *perm = perms ? perms[p] : NULL; 4773 const PetscScalar *flip = flips ? flips[p] : NULL; 4774 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 4775 } break; 4776 case ADD_ALL_VALUES: 4777 for (p = 0; p < numPoints; p++) { 4778 const PetscInt point = points[2*p]; 4779 const PetscInt *perm = perms ? perms[p] : NULL; 4780 const PetscScalar *flip = flips ? flips[p] : NULL; 4781 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 4782 } break; 4783 default: 4784 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4785 } 4786 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4787 } 4788 /* Cleanup points */ 4789 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4790 /* Cleanup array */ 4791 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4792 PetscFunctionReturn(0); 4793 } 4794 4795 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 4796 { 4797 PetscMPIInt rank; 4798 PetscInt i, j; 4799 PetscErrorCode ierr; 4800 4801 PetscFunctionBegin; 4802 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 4803 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 4804 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 4805 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 4806 numCIndices = numCIndices ? numCIndices : numRIndices; 4807 for (i = 0; i < numRIndices; i++) { 4808 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 4809 for (j = 0; j < numCIndices; j++) { 4810 #if defined(PETSC_USE_COMPLEX) 4811 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 4812 #else 4813 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 4814 #endif 4815 } 4816 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 4817 } 4818 PetscFunctionReturn(0); 4819 } 4820 4821 /* 4822 DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 4823 4824 Input Parameters: 4825 + section - The section for this data layout 4826 . point - The point contributing dofs with these indices 4827 . off - The global offset of this point 4828 . loff - The local offset of each field 4829 . setBC - The flag determining whether to include indices of bounsary values 4830 . perm - A permutation of the dofs on this point, or NULL 4831 - indperm - A permutation of the entire indices array, or NULL 4832 4833 Output Parameter: 4834 . indices - Indices for dofs on this point 4835 4836 Level: developer 4837 4838 Note: The indices could be local or global, depending on the value of 'off'. 4839 */ 4840 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 4841 { 4842 PetscInt dof; /* The number of unknowns on this point */ 4843 PetscInt cdof; /* The number of constraints on this point */ 4844 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4845 PetscInt cind = 0, k; 4846 PetscErrorCode ierr; 4847 4848 PetscFunctionBegin; 4849 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4850 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4851 if (!cdof || setBC) { 4852 for (k = 0; k < dof; ++k) { 4853 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 4854 const PetscInt ind = indperm ? indperm[preind] : preind; 4855 4856 indices[ind] = off + k; 4857 } 4858 } else { 4859 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4860 for (k = 0; k < dof; ++k) { 4861 const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 4862 const PetscInt ind = indperm ? indperm[preind] : preind; 4863 4864 if ((cind < cdof) && (k == cdofs[cind])) { 4865 /* Insert check for returning constrained indices */ 4866 indices[ind] = -(off+k+1); 4867 ++cind; 4868 } else { 4869 indices[ind] = off+k-cind; 4870 } 4871 } 4872 } 4873 *loff += dof; 4874 PetscFunctionReturn(0); 4875 } 4876 4877 /* 4878 This version only believes the point offset from the globalSection 4879 4880 . off - The global offset of this point 4881 */ 4882 PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 4883 { 4884 PetscInt numFields, foff, f; 4885 PetscErrorCode ierr; 4886 4887 PetscFunctionBegin; 4888 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4889 for (f = 0, foff = 0; f < numFields; ++f) { 4890 PetscInt fdof, cfdof; 4891 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4892 PetscInt cind = 0, b; 4893 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 4894 4895 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4896 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 4897 if (!cfdof || setBC) { 4898 for (b = 0; b < fdof; ++b) { 4899 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 4900 const PetscInt ind = indperm ? indperm[preind] : preind; 4901 4902 indices[ind] = off+foff+b; 4903 } 4904 } else { 4905 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4906 for (b = 0; b < fdof; ++b) { 4907 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 4908 const PetscInt ind = indperm ? indperm[preind] : preind; 4909 4910 if ((cind < cfdof) && (b == fcdofs[cind])) { 4911 indices[ind] = -(off+foff+b+1); 4912 ++cind; 4913 } else { 4914 indices[ind] = off+foff+b-cind; 4915 } 4916 } 4917 } 4918 foff += (setBC ? fdof : (fdof - cfdof)); 4919 foffs[f] += fdof; 4920 } 4921 PetscFunctionReturn(0); 4922 } 4923 4924 /* 4925 This version believes the globalSection offsets for each field, rather than just the point offset 4926 4927 . foffs - The offset into 'indices' for each field, since it is segregated by field 4928 */ 4929 PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 4930 { 4931 PetscInt numFields, foff, f; 4932 PetscErrorCode ierr; 4933 4934 PetscFunctionBegin; 4935 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4936 for (f = 0; f < numFields; ++f) { 4937 PetscInt fdof, cfdof; 4938 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4939 PetscInt cind = 0, b; 4940 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 4941 4942 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4943 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 4944 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 4945 if (!cfdof || setBC) { 4946 for (b = 0; b < fdof; ++b) { 4947 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 4948 const PetscInt ind = indperm ? indperm[preind] : preind; 4949 4950 indices[ind] = foff+b; 4951 } 4952 } else { 4953 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4954 for (b = 0; b < fdof; ++b) { 4955 const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 4956 const PetscInt ind = indperm ? indperm[preind] : preind; 4957 4958 if ((cind < cfdof) && (b == fcdofs[cind])) { 4959 indices[ind] = -(foff+b+1); 4960 ++cind; 4961 } else { 4962 indices[ind] = foff+b-cind; 4963 } 4964 } 4965 } 4966 foffs[f] += fdof; 4967 } 4968 PetscFunctionReturn(0); 4969 } 4970 4971 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) 4972 { 4973 Mat cMat; 4974 PetscSection aSec, cSec; 4975 IS aIS; 4976 PetscInt aStart = -1, aEnd = -1; 4977 const PetscInt *anchors; 4978 PetscInt numFields, f, p, q, newP = 0; 4979 PetscInt newNumPoints = 0, newNumIndices = 0; 4980 PetscInt *newPoints, *indices, *newIndices; 4981 PetscInt maxAnchor, maxDof; 4982 PetscInt newOffsets[32]; 4983 PetscInt *pointMatOffsets[32]; 4984 PetscInt *newPointOffsets[32]; 4985 PetscScalar *pointMat[32]; 4986 PetscScalar *newValues=NULL,*tmpValues; 4987 PetscBool anyConstrained = PETSC_FALSE; 4988 PetscErrorCode ierr; 4989 4990 PetscFunctionBegin; 4991 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4992 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4993 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4994 4995 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 4996 /* if there are point-to-point constraints */ 4997 if (aSec) { 4998 ierr = PetscMemzero(newOffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4999 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 5000 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 5001 /* figure out how many points are going to be in the new element matrix 5002 * (we allow double counting, because it's all just going to be summed 5003 * into the global matrix anyway) */ 5004 for (p = 0; p < 2*numPoints; p+=2) { 5005 PetscInt b = points[p]; 5006 PetscInt bDof = 0, bSecDof; 5007 5008 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5009 if (!bSecDof) { 5010 continue; 5011 } 5012 if (b >= aStart && b < aEnd) { 5013 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 5014 } 5015 if (bDof) { 5016 /* this point is constrained */ 5017 /* it is going to be replaced by its anchors */ 5018 PetscInt bOff, q; 5019 5020 anyConstrained = PETSC_TRUE; 5021 newNumPoints += bDof; 5022 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 5023 for (q = 0; q < bDof; q++) { 5024 PetscInt a = anchors[bOff + q]; 5025 PetscInt aDof; 5026 5027 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 5028 newNumIndices += aDof; 5029 for (f = 0; f < numFields; ++f) { 5030 PetscInt fDof; 5031 5032 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 5033 newOffsets[f+1] += fDof; 5034 } 5035 } 5036 } 5037 else { 5038 /* this point is not constrained */ 5039 newNumPoints++; 5040 newNumIndices += bSecDof; 5041 for (f = 0; f < numFields; ++f) { 5042 PetscInt fDof; 5043 5044 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5045 newOffsets[f+1] += fDof; 5046 } 5047 } 5048 } 5049 } 5050 if (!anyConstrained) { 5051 if (outNumPoints) *outNumPoints = 0; 5052 if (outNumIndices) *outNumIndices = 0; 5053 if (outPoints) *outPoints = NULL; 5054 if (outValues) *outValues = NULL; 5055 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 5056 PetscFunctionReturn(0); 5057 } 5058 5059 if (outNumPoints) *outNumPoints = newNumPoints; 5060 if (outNumIndices) *outNumIndices = newNumIndices; 5061 5062 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 5063 5064 if (!outPoints && !outValues) { 5065 if (offsets) { 5066 for (f = 0; f <= numFields; f++) { 5067 offsets[f] = newOffsets[f]; 5068 } 5069 } 5070 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 5071 PetscFunctionReturn(0); 5072 } 5073 5074 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 5075 5076 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 5077 5078 /* workspaces */ 5079 if (numFields) { 5080 for (f = 0; f < numFields; f++) { 5081 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 5082 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 5083 } 5084 } 5085 else { 5086 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 5087 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 5088 } 5089 5090 /* get workspaces for the point-to-point matrices */ 5091 if (numFields) { 5092 PetscInt totalOffset, totalMatOffset; 5093 5094 for (p = 0; p < numPoints; p++) { 5095 PetscInt b = points[2*p]; 5096 PetscInt bDof = 0, bSecDof; 5097 5098 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5099 if (!bSecDof) { 5100 for (f = 0; f < numFields; f++) { 5101 newPointOffsets[f][p + 1] = 0; 5102 pointMatOffsets[f][p + 1] = 0; 5103 } 5104 continue; 5105 } 5106 if (b >= aStart && b < aEnd) { 5107 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5108 } 5109 if (bDof) { 5110 for (f = 0; f < numFields; f++) { 5111 PetscInt fDof, q, bOff, allFDof = 0; 5112 5113 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5114 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5115 for (q = 0; q < bDof; q++) { 5116 PetscInt a = anchors[bOff + q]; 5117 PetscInt aFDof; 5118 5119 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 5120 allFDof += aFDof; 5121 } 5122 newPointOffsets[f][p+1] = allFDof; 5123 pointMatOffsets[f][p+1] = fDof * allFDof; 5124 } 5125 } 5126 else { 5127 for (f = 0; f < numFields; f++) { 5128 PetscInt fDof; 5129 5130 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5131 newPointOffsets[f][p+1] = fDof; 5132 pointMatOffsets[f][p+1] = 0; 5133 } 5134 } 5135 } 5136 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 5137 newPointOffsets[f][0] = totalOffset; 5138 pointMatOffsets[f][0] = totalMatOffset; 5139 for (p = 0; p < numPoints; p++) { 5140 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 5141 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 5142 } 5143 totalOffset = newPointOffsets[f][numPoints]; 5144 totalMatOffset = pointMatOffsets[f][numPoints]; 5145 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 5146 } 5147 } 5148 else { 5149 for (p = 0; p < numPoints; p++) { 5150 PetscInt b = points[2*p]; 5151 PetscInt bDof = 0, bSecDof; 5152 5153 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5154 if (!bSecDof) { 5155 newPointOffsets[0][p + 1] = 0; 5156 pointMatOffsets[0][p + 1] = 0; 5157 continue; 5158 } 5159 if (b >= aStart && b < aEnd) { 5160 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5161 } 5162 if (bDof) { 5163 PetscInt bOff, q, allDof = 0; 5164 5165 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5166 for (q = 0; q < bDof; q++) { 5167 PetscInt a = anchors[bOff + q], aDof; 5168 5169 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 5170 allDof += aDof; 5171 } 5172 newPointOffsets[0][p+1] = allDof; 5173 pointMatOffsets[0][p+1] = bSecDof * allDof; 5174 } 5175 else { 5176 newPointOffsets[0][p+1] = bSecDof; 5177 pointMatOffsets[0][p+1] = 0; 5178 } 5179 } 5180 newPointOffsets[0][0] = 0; 5181 pointMatOffsets[0][0] = 0; 5182 for (p = 0; p < numPoints; p++) { 5183 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 5184 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 5185 } 5186 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 5187 } 5188 5189 /* output arrays */ 5190 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5191 5192 /* get the point-to-point matrices; construct newPoints */ 5193 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 5194 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 5195 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 5196 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 5197 if (numFields) { 5198 for (p = 0, newP = 0; p < numPoints; p++) { 5199 PetscInt b = points[2*p]; 5200 PetscInt o = points[2*p+1]; 5201 PetscInt bDof = 0, bSecDof; 5202 5203 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 5204 if (!bSecDof) { 5205 continue; 5206 } 5207 if (b >= aStart && b < aEnd) { 5208 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5209 } 5210 if (bDof) { 5211 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 5212 5213 fStart[0] = 0; 5214 fEnd[0] = 0; 5215 for (f = 0; f < numFields; f++) { 5216 PetscInt fDof; 5217 5218 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 5219 fStart[f+1] = fStart[f] + fDof; 5220 fEnd[f+1] = fStart[f+1]; 5221 } 5222 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 5223 ierr = DMPlexGetIndicesPointFields_Internal(cSec, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 5224 5225 fAnchorStart[0] = 0; 5226 fAnchorEnd[0] = 0; 5227 for (f = 0; f < numFields; f++) { 5228 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 5229 5230 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 5231 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 5232 } 5233 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5234 for (q = 0; q < bDof; q++) { 5235 PetscInt a = anchors[bOff + q], aOff; 5236 5237 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 5238 newPoints[2*(newP + q)] = a; 5239 newPoints[2*(newP + q) + 1] = 0; 5240 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 5241 ierr = DMPlexGetIndicesPointFields_Internal(section, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 5242 } 5243 newP += bDof; 5244 5245 if (outValues) { 5246 /* get the point-to-point submatrix */ 5247 for (f = 0; f < numFields; f++) { 5248 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 5249 } 5250 } 5251 } 5252 else { 5253 newPoints[2 * newP] = b; 5254 newPoints[2 * newP + 1] = o; 5255 newP++; 5256 } 5257 } 5258 } else { 5259 for (p = 0; p < numPoints; p++) { 5260 PetscInt b = points[2*p]; 5261 PetscInt o = points[2*p+1]; 5262 PetscInt bDof = 0, bSecDof; 5263 5264 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 5265 if (!bSecDof) { 5266 continue; 5267 } 5268 if (b >= aStart && b < aEnd) { 5269 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5270 } 5271 if (bDof) { 5272 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 5273 5274 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 5275 ierr = DMPlexGetIndicesPoint_Internal(cSec, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 5276 5277 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 5278 for (q = 0; q < bDof; q++) { 5279 PetscInt a = anchors[bOff + q], aOff; 5280 5281 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 5282 5283 newPoints[2*(newP + q)] = a; 5284 newPoints[2*(newP + q) + 1] = 0; 5285 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 5286 ierr = DMPlexGetIndicesPoint_Internal(section, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 5287 } 5288 newP += bDof; 5289 5290 /* get the point-to-point submatrix */ 5291 if (outValues) { 5292 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 5293 } 5294 } 5295 else { 5296 newPoints[2 * newP] = b; 5297 newPoints[2 * newP + 1] = o; 5298 newP++; 5299 } 5300 } 5301 } 5302 5303 if (outValues) { 5304 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 5305 ierr = PetscMemzero(tmpValues,newNumIndices*numIndices*sizeof(*tmpValues));CHKERRQ(ierr); 5306 /* multiply constraints on the right */ 5307 if (numFields) { 5308 for (f = 0; f < numFields; f++) { 5309 PetscInt oldOff = offsets[f]; 5310 5311 for (p = 0; p < numPoints; p++) { 5312 PetscInt cStart = newPointOffsets[f][p]; 5313 PetscInt b = points[2 * p]; 5314 PetscInt c, r, k; 5315 PetscInt dof; 5316 5317 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 5318 if (!dof) { 5319 continue; 5320 } 5321 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 5322 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 5323 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 5324 5325 for (r = 0; r < numIndices; r++) { 5326 for (c = 0; c < nCols; c++) { 5327 for (k = 0; k < dof; k++) { 5328 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 5329 } 5330 } 5331 } 5332 } 5333 else { 5334 /* copy this column as is */ 5335 for (r = 0; r < numIndices; r++) { 5336 for (c = 0; c < dof; c++) { 5337 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 5338 } 5339 } 5340 } 5341 oldOff += dof; 5342 } 5343 } 5344 } 5345 else { 5346 PetscInt oldOff = 0; 5347 for (p = 0; p < numPoints; p++) { 5348 PetscInt cStart = newPointOffsets[0][p]; 5349 PetscInt b = points[2 * p]; 5350 PetscInt c, r, k; 5351 PetscInt dof; 5352 5353 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 5354 if (!dof) { 5355 continue; 5356 } 5357 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 5358 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 5359 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 5360 5361 for (r = 0; r < numIndices; r++) { 5362 for (c = 0; c < nCols; c++) { 5363 for (k = 0; k < dof; k++) { 5364 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 5365 } 5366 } 5367 } 5368 } 5369 else { 5370 /* copy this column as is */ 5371 for (r = 0; r < numIndices; r++) { 5372 for (c = 0; c < dof; c++) { 5373 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 5374 } 5375 } 5376 } 5377 oldOff += dof; 5378 } 5379 } 5380 5381 if (multiplyLeft) { 5382 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 5383 ierr = PetscMemzero(newValues,newNumIndices*newNumIndices*sizeof(*newValues));CHKERRQ(ierr); 5384 /* multiply constraints transpose on the left */ 5385 if (numFields) { 5386 for (f = 0; f < numFields; f++) { 5387 PetscInt oldOff = offsets[f]; 5388 5389 for (p = 0; p < numPoints; p++) { 5390 PetscInt rStart = newPointOffsets[f][p]; 5391 PetscInt b = points[2 * p]; 5392 PetscInt c, r, k; 5393 PetscInt dof; 5394 5395 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 5396 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 5397 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 5398 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 5399 5400 for (r = 0; r < nRows; r++) { 5401 for (c = 0; c < newNumIndices; c++) { 5402 for (k = 0; k < dof; k++) { 5403 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 5404 } 5405 } 5406 } 5407 } 5408 else { 5409 /* copy this row as is */ 5410 for (r = 0; r < dof; r++) { 5411 for (c = 0; c < newNumIndices; c++) { 5412 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 5413 } 5414 } 5415 } 5416 oldOff += dof; 5417 } 5418 } 5419 } 5420 else { 5421 PetscInt oldOff = 0; 5422 5423 for (p = 0; p < numPoints; p++) { 5424 PetscInt rStart = newPointOffsets[0][p]; 5425 PetscInt b = points[2 * p]; 5426 PetscInt c, r, k; 5427 PetscInt dof; 5428 5429 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 5430 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 5431 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 5432 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 5433 5434 for (r = 0; r < nRows; r++) { 5435 for (c = 0; c < newNumIndices; c++) { 5436 for (k = 0; k < dof; k++) { 5437 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 5438 } 5439 } 5440 } 5441 } 5442 else { 5443 /* copy this row as is */ 5444 for (r = 0; r < dof; r++) { 5445 for (c = 0; c < newNumIndices; c++) { 5446 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 5447 } 5448 } 5449 } 5450 oldOff += dof; 5451 } 5452 } 5453 5454 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 5455 } 5456 else { 5457 newValues = tmpValues; 5458 } 5459 } 5460 5461 /* clean up */ 5462 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 5463 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 5464 5465 if (numFields) { 5466 for (f = 0; f < numFields; f++) { 5467 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 5468 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 5469 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 5470 } 5471 } 5472 else { 5473 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 5474 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 5475 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 5476 } 5477 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 5478 5479 /* output */ 5480 if (outPoints) { 5481 *outPoints = newPoints; 5482 } 5483 else { 5484 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5485 } 5486 if (outValues) { 5487 *outValues = newValues; 5488 } 5489 for (f = 0; f <= numFields; f++) { 5490 offsets[f] = newOffsets[f]; 5491 } 5492 PetscFunctionReturn(0); 5493 } 5494 5495 /*@C 5496 DMPlexGetClosureIndices - Get the global indices in a vector v for all points in the closure of the given point 5497 5498 Not collective 5499 5500 Input Parameters: 5501 + dm - The DM 5502 . section - The section describing the layout in v, or NULL to use the default section 5503 . globalSection - The section describing the parallel layout in v, or NULL to use the default section 5504 - point - The mesh point 5505 5506 Output parameters: 5507 + numIndices - The number of indices 5508 . indices - The indices 5509 - outOffsets - Field offset if not NULL 5510 5511 Note: Must call DMPlexRestoreClosureIndices() to free allocated memory 5512 5513 Level: advanced 5514 5515 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure() 5516 @*/ 5517 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices, PetscInt *outOffsets) 5518 { 5519 PetscSection clSection; 5520 IS clPoints; 5521 const PetscInt *clp, *clperm; 5522 const PetscInt **perms[32] = {NULL}; 5523 PetscInt *points = NULL, *pointsNew; 5524 PetscInt numPoints, numPointsNew; 5525 PetscInt offsets[32]; 5526 PetscInt Nf, Nind, NindNew, off, globalOff, f, p; 5527 PetscErrorCode ierr; 5528 5529 PetscFunctionBegin; 5530 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5531 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5532 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 5533 if (numIndices) PetscValidPointer(numIndices, 4); 5534 PetscValidPointer(indices, 5); 5535 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5536 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 5537 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5538 /* Get points in closure */ 5539 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5540 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 5541 /* Get number of indices and indices per field */ 5542 for (p = 0, Nind = 0; p < numPoints*2; p += 2) { 5543 PetscInt dof, fdof; 5544 5545 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5546 for (f = 0; f < Nf; ++f) { 5547 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5548 offsets[f+1] += fdof; 5549 } 5550 Nind += dof; 5551 } 5552 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 5553 if (Nf && offsets[Nf] != Nind) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Nind); 5554 if (!Nf) offsets[1] = Nind; 5555 /* Get dual space symmetries */ 5556 for (f = 0; f < PetscMax(1,Nf); f++) { 5557 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5558 else {ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5559 } 5560 /* Correct for hanging node constraints */ 5561 { 5562 ierr = DMPlexAnchorsModifyMat(dm, section, numPoints, Nind, points, perms, NULL, &numPointsNew, &NindNew, &pointsNew, NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 5563 if (numPointsNew) { 5564 for (f = 0; f < PetscMax(1,Nf); f++) { 5565 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5566 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5567 } 5568 for (f = 0; f < PetscMax(1,Nf); f++) { 5569 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section,f,numPointsNew,pointsNew,&perms[f],NULL);CHKERRQ(ierr);} 5570 else {ierr = PetscSectionGetPointSyms(section,numPointsNew,pointsNew,&perms[f],NULL);CHKERRQ(ierr);} 5571 } 5572 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5573 numPoints = numPointsNew; 5574 Nind = NindNew; 5575 points = pointsNew; 5576 } 5577 } 5578 /* Calculate indices */ 5579 ierr = DMGetWorkArray(dm, Nind, MPIU_INT, indices);CHKERRQ(ierr); 5580 if (Nf) { 5581 if (outOffsets) { 5582 PetscInt f; 5583 5584 for (f = 0; f <= Nf; f++) { 5585 outOffsets[f] = offsets[f]; 5586 } 5587 } 5588 for (p = 0; p < numPoints; p++) { 5589 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5590 DMPlexGetIndicesPointFields_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, perms, p, clperm, *indices); 5591 } 5592 } else { 5593 for (p = 0, off = 0; p < numPoints; p++) { 5594 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 5595 5596 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5597 DMPlexGetIndicesPoint_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, clperm, *indices); 5598 } 5599 } 5600 /* Cleanup points */ 5601 for (f = 0; f < PetscMax(1,Nf); f++) { 5602 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5603 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5604 } 5605 if (numPointsNew) { 5606 ierr = DMRestoreWorkArray(dm, 2*numPointsNew, MPIU_INT, &pointsNew);CHKERRQ(ierr); 5607 } else { 5608 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5609 } 5610 if (numIndices) *numIndices = Nind; 5611 PetscFunctionReturn(0); 5612 } 5613 5614 /*@C 5615 DMPlexRestoreClosureIndices - Restore the indices in a vector v for all points in the closure of the given point 5616 5617 Not collective 5618 5619 Input Parameters: 5620 + dm - The DM 5621 . section - The section describing the layout in v, or NULL to use the default section 5622 . globalSection - The section describing the parallel layout in v, or NULL to use the default section 5623 . point - The mesh point 5624 . numIndices - The number of indices 5625 . indices - The indices 5626 - outOffsets - Field offset if not NULL 5627 5628 Level: advanced 5629 5630 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure() 5631 @*/ 5632 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices,PetscInt *outOffsets) 5633 { 5634 PetscErrorCode ierr; 5635 5636 PetscFunctionBegin; 5637 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5638 PetscValidPointer(indices, 5); 5639 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 5640 PetscFunctionReturn(0); 5641 } 5642 5643 /*@C 5644 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 5645 5646 Not collective 5647 5648 Input Parameters: 5649 + dm - The DM 5650 . section - The section describing the layout in v, or NULL to use the default section 5651 . globalSection - The section describing the layout in v, or NULL to use the default global section 5652 . A - The matrix 5653 . point - The point in the DM 5654 . values - The array of values 5655 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 5656 5657 Fortran Notes: 5658 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 5659 5660 Level: intermediate 5661 5662 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 5663 @*/ 5664 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5665 { 5666 DM_Plex *mesh = (DM_Plex*) dm->data; 5667 PetscSection clSection; 5668 IS clPoints; 5669 PetscInt *points = NULL, *newPoints; 5670 const PetscInt *clp, *clperm; 5671 PetscInt *indices; 5672 PetscInt offsets[32]; 5673 const PetscInt **perms[32] = {NULL}; 5674 const PetscScalar **flips[32] = {NULL}; 5675 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, p, f; 5676 PetscScalar *valCopy = NULL; 5677 PetscScalar *newValues; 5678 PetscErrorCode ierr; 5679 5680 PetscFunctionBegin; 5681 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5682 if (!section) {ierr = DMGetSection(dm, §ion);CHKERRQ(ierr);} 5683 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5684 if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 5685 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 5686 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 5687 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5688 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5689 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5690 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 5691 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5692 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 5693 PetscInt fdof; 5694 5695 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5696 for (f = 0; f < numFields; ++f) { 5697 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5698 offsets[f+1] += fdof; 5699 } 5700 numIndices += dof; 5701 } 5702 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 5703 5704 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[numFields], numIndices); 5705 /* Get symmetries */ 5706 for (f = 0; f < PetscMax(1,numFields); f++) { 5707 if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5708 else {ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5709 if (values && flips[f]) { /* may need to apply sign changes to the element matrix */ 5710 PetscInt foffset = offsets[f]; 5711 5712 for (p = 0; p < numPoints; p++) { 5713 PetscInt point = points[2*p], fdof; 5714 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 5715 5716 if (!numFields) { 5717 ierr = PetscSectionGetDof(section,point,&fdof);CHKERRQ(ierr); 5718 } else { 5719 ierr = PetscSectionGetFieldDof(section,point,f,&fdof);CHKERRQ(ierr); 5720 } 5721 if (flip) { 5722 PetscInt i, j, k; 5723 5724 if (!valCopy) { 5725 ierr = DMGetWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 5726 for (j = 0; j < numIndices * numIndices; j++) valCopy[j] = values[j]; 5727 values = valCopy; 5728 } 5729 for (i = 0; i < fdof; i++) { 5730 PetscScalar fval = flip[i]; 5731 5732 for (k = 0; k < numIndices; k++) { 5733 valCopy[numIndices * (foffset + i) + k] *= fval; 5734 valCopy[numIndices * k + (foffset + i)] *= fval; 5735 } 5736 } 5737 } 5738 foffset += fdof; 5739 } 5740 } 5741 } 5742 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,perms,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets,PETSC_TRUE);CHKERRQ(ierr); 5743 if (newNumPoints) { 5744 if (valCopy) { 5745 ierr = DMRestoreWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 5746 } 5747 for (f = 0; f < PetscMax(1,numFields); f++) { 5748 if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5749 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5750 } 5751 for (f = 0; f < PetscMax(1,numFields); f++) { 5752 if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,newNumPoints,newPoints,&perms[f],&flips[f]);CHKERRQ(ierr);} 5753 else {ierr = PetscSectionGetPointSyms(section,newNumPoints,newPoints,&perms[f],&flips[f]);CHKERRQ(ierr);} 5754 } 5755 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5756 numPoints = newNumPoints; 5757 numIndices = newNumIndices; 5758 points = newPoints; 5759 values = newValues; 5760 } 5761 ierr = DMGetWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr); 5762 if (numFields) { 5763 PetscBool useFieldOffsets; 5764 5765 ierr = PetscSectionGetUseFieldOffsets(globalSection, &useFieldOffsets);CHKERRQ(ierr); 5766 if (useFieldOffsets) { 5767 for (p = 0; p < numPoints; p++) { 5768 DMPlexGetIndicesPointFieldsSplit_Internal(section, globalSection, points[2*p], offsets, PETSC_FALSE, perms, p, clperm, indices); 5769 } 5770 } else { 5771 for (p = 0; p < numPoints; p++) { 5772 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5773 DMPlexGetIndicesPointFields_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, perms, p, clperm, indices); 5774 } 5775 } 5776 } else { 5777 for (p = 0, off = 0; p < numPoints; p++) { 5778 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 5779 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5780 DMPlexGetIndicesPoint_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, clperm, indices); 5781 } 5782 } 5783 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 5784 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 5785 if (mesh->printFEM > 1) { 5786 PetscInt i; 5787 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 5788 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 5789 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5790 } 5791 if (ierr) { 5792 PetscMPIInt rank; 5793 PetscErrorCode ierr2; 5794 5795 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5796 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5797 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 5798 ierr2 = DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr2); 5799 CHKERRQ(ierr); 5800 } 5801 for (f = 0; f < PetscMax(1,numFields); f++) { 5802 if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5803 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5804 } 5805 if (newNumPoints) { 5806 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 5807 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5808 } 5809 else { 5810 if (valCopy) { 5811 ierr = DMRestoreWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 5812 } 5813 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5814 } 5815 ierr = DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr); 5816 PetscFunctionReturn(0); 5817 } 5818 5819 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5820 { 5821 DM_Plex *mesh = (DM_Plex*) dmf->data; 5822 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5823 PetscInt *cpoints = NULL; 5824 PetscInt *findices, *cindices; 5825 const PetscInt *fclperm, *cclperm; 5826 PetscInt foffsets[32], coffsets[32]; 5827 CellRefiner cellRefiner; 5828 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5829 PetscErrorCode ierr; 5830 5831 PetscFunctionBegin; 5832 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5833 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5834 if (!fsection) {ierr = DMGetSection(dmf, &fsection);CHKERRQ(ierr);} 5835 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5836 if (!csection) {ierr = DMGetSection(dmc, &csection);CHKERRQ(ierr);} 5837 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5838 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5839 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5840 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5841 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5842 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 5843 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5844 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5845 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5846 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5847 ierr = PetscSectionGetClosureInversePermutation_Internal(fsection, (PetscObject) dmf, NULL, &fclperm);CHKERRQ(ierr); 5848 ierr = PetscSectionGetClosureInversePermutation_Internal(csection, (PetscObject) dmc, NULL, &cclperm);CHKERRQ(ierr); 5849 /* Column indices */ 5850 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5851 maxFPoints = numCPoints; 5852 /* Compress out points not in the section */ 5853 /* TODO: Squeeze out points with 0 dof as well */ 5854 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5855 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5856 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5857 cpoints[q*2] = cpoints[p]; 5858 cpoints[q*2+1] = cpoints[p+1]; 5859 ++q; 5860 } 5861 } 5862 numCPoints = q; 5863 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5864 PetscInt fdof; 5865 5866 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5867 if (!dof) continue; 5868 for (f = 0; f < numFields; ++f) { 5869 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5870 coffsets[f+1] += fdof; 5871 } 5872 numCIndices += dof; 5873 } 5874 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5875 /* Row indices */ 5876 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5877 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5878 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 5879 for (r = 0, q = 0; r < numSubcells; ++r) { 5880 /* TODO Map from coarse to fine cells */ 5881 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5882 /* Compress out points not in the section */ 5883 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5884 for (p = 0; p < numFPoints*2; p += 2) { 5885 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5886 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5887 if (!dof) continue; 5888 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5889 if (s < q) continue; 5890 ftotpoints[q*2] = fpoints[p]; 5891 ftotpoints[q*2+1] = fpoints[p+1]; 5892 ++q; 5893 } 5894 } 5895 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5896 } 5897 numFPoints = q; 5898 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5899 PetscInt fdof; 5900 5901 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5902 if (!dof) continue; 5903 for (f = 0; f < numFields; ++f) { 5904 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5905 foffsets[f+1] += fdof; 5906 } 5907 numFIndices += dof; 5908 } 5909 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5910 5911 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 5912 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 5913 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 5914 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 5915 if (numFields) { 5916 const PetscInt **permsF[32] = {NULL}; 5917 const PetscInt **permsC[32] = {NULL}; 5918 5919 for (f = 0; f < numFields; f++) { 5920 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 5921 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 5922 } 5923 for (p = 0; p < numFPoints; p++) { 5924 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 5925 ierr = DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 5926 } 5927 for (p = 0; p < numCPoints; p++) { 5928 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 5929 ierr = DMPlexGetIndicesPointFields_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 5930 } 5931 for (f = 0; f < numFields; f++) { 5932 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 5933 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 5934 } 5935 } else { 5936 const PetscInt **permsF = NULL; 5937 const PetscInt **permsC = NULL; 5938 5939 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 5940 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 5941 for (p = 0, off = 0; p < numFPoints; p++) { 5942 const PetscInt *perm = permsF ? permsF[p] : NULL; 5943 5944 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 5945 ierr = DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 5946 } 5947 for (p = 0, off = 0; p < numCPoints; p++) { 5948 const PetscInt *perm = permsC ? permsC[p] : NULL; 5949 5950 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 5951 ierr = DMPlexGetIndicesPoint_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 5952 } 5953 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 5954 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 5955 } 5956 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 5957 /* TODO: flips */ 5958 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 5959 if (ierr) { 5960 PetscMPIInt rank; 5961 PetscErrorCode ierr2; 5962 5963 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5964 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5965 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 5966 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 5967 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 5968 CHKERRQ(ierr); 5969 } 5970 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 5971 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5972 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 5973 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 5974 PetscFunctionReturn(0); 5975 } 5976 5977 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 5978 { 5979 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5980 PetscInt *cpoints = NULL; 5981 PetscInt foffsets[32], coffsets[32]; 5982 const PetscInt *fclperm, *cclperm; 5983 CellRefiner cellRefiner; 5984 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5985 PetscErrorCode ierr; 5986 5987 PetscFunctionBegin; 5988 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5989 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5990 if (!fsection) {ierr = DMGetSection(dmf, &fsection);CHKERRQ(ierr);} 5991 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5992 if (!csection) {ierr = DMGetSection(dmc, &csection);CHKERRQ(ierr);} 5993 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5994 if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5995 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5996 if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5997 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5998 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5999 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6000 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6001 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6002 ierr = PetscSectionGetClosureInversePermutation_Internal(fsection, (PetscObject) dmf, NULL, &fclperm);CHKERRQ(ierr); 6003 ierr = PetscSectionGetClosureInversePermutation_Internal(csection, (PetscObject) dmc, NULL, &cclperm);CHKERRQ(ierr); 6004 /* Column indices */ 6005 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 6006 maxFPoints = numCPoints; 6007 /* Compress out points not in the section */ 6008 /* TODO: Squeeze out points with 0 dof as well */ 6009 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 6010 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 6011 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 6012 cpoints[q*2] = cpoints[p]; 6013 cpoints[q*2+1] = cpoints[p+1]; 6014 ++q; 6015 } 6016 } 6017 numCPoints = q; 6018 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 6019 PetscInt fdof; 6020 6021 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 6022 if (!dof) continue; 6023 for (f = 0; f < numFields; ++f) { 6024 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 6025 coffsets[f+1] += fdof; 6026 } 6027 numCIndices += dof; 6028 } 6029 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 6030 /* Row indices */ 6031 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 6032 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 6033 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6034 for (r = 0, q = 0; r < numSubcells; ++r) { 6035 /* TODO Map from coarse to fine cells */ 6036 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6037 /* Compress out points not in the section */ 6038 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 6039 for (p = 0; p < numFPoints*2; p += 2) { 6040 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 6041 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 6042 if (!dof) continue; 6043 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 6044 if (s < q) continue; 6045 ftotpoints[q*2] = fpoints[p]; 6046 ftotpoints[q*2+1] = fpoints[p+1]; 6047 ++q; 6048 } 6049 } 6050 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6051 } 6052 numFPoints = q; 6053 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 6054 PetscInt fdof; 6055 6056 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 6057 if (!dof) continue; 6058 for (f = 0; f < numFields; ++f) { 6059 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 6060 foffsets[f+1] += fdof; 6061 } 6062 numFIndices += dof; 6063 } 6064 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 6065 6066 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 6067 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 6068 if (numFields) { 6069 const PetscInt **permsF[32] = {NULL}; 6070 const PetscInt **permsC[32] = {NULL}; 6071 6072 for (f = 0; f < numFields; f++) { 6073 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 6074 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6075 } 6076 for (p = 0; p < numFPoints; p++) { 6077 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6078 DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices); 6079 } 6080 for (p = 0; p < numCPoints; p++) { 6081 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 6082 DMPlexGetIndicesPointFields_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices); 6083 } 6084 for (f = 0; f < numFields; f++) { 6085 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 6086 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6087 } 6088 } else { 6089 const PetscInt **permsF = NULL; 6090 const PetscInt **permsC = NULL; 6091 6092 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 6093 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6094 for (p = 0, off = 0; p < numFPoints; p++) { 6095 const PetscInt *perm = permsF ? permsF[p] : NULL; 6096 6097 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6098 DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices); 6099 } 6100 for (p = 0, off = 0; p < numCPoints; p++) { 6101 const PetscInt *perm = permsC ? permsC[p] : NULL; 6102 6103 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 6104 DMPlexGetIndicesPoint_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices); 6105 } 6106 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 6107 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6108 } 6109 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6110 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 6111 PetscFunctionReturn(0); 6112 } 6113 6114 /*@ 6115 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 6116 6117 Input Parameter: 6118 . dm - The DMPlex object 6119 6120 Output Parameters: 6121 + cMax - The first hybrid cell 6122 . fMax - The first hybrid face 6123 . eMax - The first hybrid edge 6124 - vMax - The first hybrid vertex 6125 6126 Level: developer 6127 6128 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 6129 @*/ 6130 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 6131 { 6132 DM_Plex *mesh = (DM_Plex*) dm->data; 6133 PetscInt dim; 6134 PetscErrorCode ierr; 6135 6136 PetscFunctionBegin; 6137 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6138 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6139 if (dim < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM dimension not yet set"); 6140 if (cMax) *cMax = mesh->hybridPointMax[dim]; 6141 if (fMax) *fMax = mesh->hybridPointMax[PetscMax(dim-1,0)]; 6142 if (eMax) *eMax = mesh->hybridPointMax[1]; 6143 if (vMax) *vMax = mesh->hybridPointMax[0]; 6144 PetscFunctionReturn(0); 6145 } 6146 6147 static PetscErrorCode DMPlexCreateDimStratum(DM dm, DMLabel depthLabel, DMLabel dimLabel, PetscInt d, PetscInt dMax) 6148 { 6149 IS is, his; 6150 PetscInt first = 0, stride; 6151 PetscBool isStride; 6152 PetscErrorCode ierr; 6153 6154 PetscFunctionBegin; 6155 ierr = DMLabelGetStratumIS(depthLabel, d, &is);CHKERRQ(ierr); 6156 ierr = PetscObjectTypeCompare((PetscObject) is, ISSTRIDE, &isStride);CHKERRQ(ierr); 6157 if (isStride) { 6158 ierr = ISStrideGetInfo(is, &first, &stride);CHKERRQ(ierr); 6159 } 6160 if (is && (!isStride || stride != 1)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM is not stratified: depth %D IS is not contiguous", d); 6161 ierr = ISCreateStride(PETSC_COMM_SELF, (dMax - first), first, 1, &his);CHKERRQ(ierr); 6162 ierr = DMLabelSetStratumIS(dimLabel, d, his);CHKERRQ(ierr); 6163 ierr = ISDestroy(&his);CHKERRQ(ierr); 6164 ierr = ISDestroy(&is);CHKERRQ(ierr); 6165 PetscFunctionReturn(0); 6166 } 6167 6168 /*@ 6169 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 6170 6171 Input Parameters: 6172 . dm - The DMPlex object 6173 . cMax - The first hybrid cell 6174 . fMax - The first hybrid face 6175 . eMax - The first hybrid edge 6176 - vMax - The first hybrid vertex 6177 6178 Level: developer 6179 6180 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 6181 @*/ 6182 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 6183 { 6184 DM_Plex *mesh = (DM_Plex*) dm->data; 6185 PetscInt dim; 6186 PetscErrorCode ierr; 6187 6188 PetscFunctionBegin; 6189 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6190 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6191 if (dim < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM dimension not yet set"); 6192 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 6193 if (fMax >= 0) mesh->hybridPointMax[PetscMax(dim-1,0)] = fMax; 6194 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 6195 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 6196 PetscFunctionReturn(0); 6197 } 6198 6199 /*@C 6200 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 6201 6202 Input Parameter: 6203 . dm - The DMPlex object 6204 6205 Output Parameter: 6206 . cellHeight - The height of a cell 6207 6208 Level: developer 6209 6210 .seealso DMPlexSetVTKCellHeight() 6211 @*/ 6212 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 6213 { 6214 DM_Plex *mesh = (DM_Plex*) dm->data; 6215 6216 PetscFunctionBegin; 6217 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6218 PetscValidPointer(cellHeight, 2); 6219 *cellHeight = mesh->vtkCellHeight; 6220 PetscFunctionReturn(0); 6221 } 6222 6223 /*@C 6224 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 6225 6226 Input Parameters: 6227 + dm - The DMPlex object 6228 - cellHeight - The height of a cell 6229 6230 Level: developer 6231 6232 .seealso DMPlexGetVTKCellHeight() 6233 @*/ 6234 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 6235 { 6236 DM_Plex *mesh = (DM_Plex*) dm->data; 6237 6238 PetscFunctionBegin; 6239 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6240 mesh->vtkCellHeight = cellHeight; 6241 PetscFunctionReturn(0); 6242 } 6243 6244 /* We can easily have a form that takes an IS instead */ 6245 PetscErrorCode DMPlexCreateNumbering_Internal(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 6246 { 6247 PetscSection section, globalSection; 6248 PetscInt *numbers, p; 6249 PetscErrorCode ierr; 6250 6251 PetscFunctionBegin; 6252 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 6253 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 6254 for (p = pStart; p < pEnd; ++p) { 6255 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 6256 } 6257 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 6258 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 6259 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 6260 for (p = pStart; p < pEnd; ++p) { 6261 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 6262 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 6263 else numbers[p-pStart] += shift; 6264 } 6265 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 6266 if (globalSize) { 6267 PetscLayout layout; 6268 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 6269 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 6270 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 6271 } 6272 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6273 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 6274 PetscFunctionReturn(0); 6275 } 6276 6277 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 6278 { 6279 PetscInt cellHeight, cStart, cEnd, cMax; 6280 PetscErrorCode ierr; 6281 6282 PetscFunctionBegin; 6283 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 6284 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 6285 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 6286 if (cMax >= 0 && !includeHybrid) cEnd = PetscMin(cEnd, cMax); 6287 ierr = DMPlexCreateNumbering_Internal(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 6288 PetscFunctionReturn(0); 6289 } 6290 6291 /*@ 6292 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 6293 6294 Input Parameter: 6295 . dm - The DMPlex object 6296 6297 Output Parameter: 6298 . globalCellNumbers - Global cell numbers for all cells on this process 6299 6300 Level: developer 6301 6302 .seealso DMPlexGetVertexNumbering() 6303 @*/ 6304 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 6305 { 6306 DM_Plex *mesh = (DM_Plex*) dm->data; 6307 PetscErrorCode ierr; 6308 6309 PetscFunctionBegin; 6310 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6311 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 6312 *globalCellNumbers = mesh->globalCellNumbers; 6313 PetscFunctionReturn(0); 6314 } 6315 6316 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 6317 { 6318 PetscInt vStart, vEnd, vMax; 6319 PetscErrorCode ierr; 6320 6321 PetscFunctionBegin; 6322 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6323 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6324 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 6325 if (vMax >= 0 && !includeHybrid) vEnd = PetscMin(vEnd, vMax); 6326 ierr = DMPlexCreateNumbering_Internal(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 6327 PetscFunctionReturn(0); 6328 } 6329 6330 /*@ 6331 DMPlexGetVertexNumbering - Get a global certex numbering for all vertices on this process 6332 6333 Input Parameter: 6334 . dm - The DMPlex object 6335 6336 Output Parameter: 6337 . globalVertexNumbers - Global vertex numbers for all vertices on this process 6338 6339 Level: developer 6340 6341 .seealso DMPlexGetCellNumbering() 6342 @*/ 6343 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 6344 { 6345 DM_Plex *mesh = (DM_Plex*) dm->data; 6346 PetscErrorCode ierr; 6347 6348 PetscFunctionBegin; 6349 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6350 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 6351 *globalVertexNumbers = mesh->globalVertexNumbers; 6352 PetscFunctionReturn(0); 6353 } 6354 6355 /*@ 6356 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 6357 6358 Input Parameter: 6359 . dm - The DMPlex object 6360 6361 Output Parameter: 6362 . globalPointNumbers - Global numbers for all points on this process 6363 6364 Level: developer 6365 6366 .seealso DMPlexGetCellNumbering() 6367 @*/ 6368 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 6369 { 6370 IS nums[4]; 6371 PetscInt depths[4], gdepths[4], starts[4]; 6372 PetscInt depth, d, shift = 0; 6373 PetscErrorCode ierr; 6374 6375 PetscFunctionBegin; 6376 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6377 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6378 /* For unstratified meshes use dim instead of depth */ 6379 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 6380 for (d = 0; d <= depth; ++d) { 6381 PetscInt end; 6382 6383 depths[d] = depth-d; 6384 ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 6385 if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 6386 } 6387 ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 6388 ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 6389 for (d = 0; d <= depth; ++d) { 6390 if (starts[d] >= 0 && depths[d] != gdepths[d]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 6391 } 6392 for (d = 0; d <= depth; ++d) { 6393 PetscInt pStart, pEnd, gsize; 6394 6395 ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 6396 ierr = DMPlexCreateNumbering_Internal(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 6397 shift += gsize; 6398 } 6399 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 6400 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 6401 PetscFunctionReturn(0); 6402 } 6403 6404 6405 /*@ 6406 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 6407 6408 Input Parameter: 6409 . dm - The DMPlex object 6410 6411 Output Parameter: 6412 . ranks - The rank field 6413 6414 Options Database Keys: 6415 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 6416 6417 Level: intermediate 6418 6419 .seealso: DMView() 6420 @*/ 6421 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 6422 { 6423 DM rdm; 6424 PetscFE fe; 6425 PetscScalar *r; 6426 PetscMPIInt rank; 6427 PetscInt dim, cStart, cEnd, c; 6428 PetscErrorCode ierr; 6429 6430 PetscFunctionBeginUser; 6431 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6432 PetscValidPointer(ranks, 2); 6433 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 6434 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 6435 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 6436 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 6437 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 6438 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 6439 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 6440 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 6441 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6442 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 6443 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 6444 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 6445 for (c = cStart; c < cEnd; ++c) { 6446 PetscScalar *lr; 6447 6448 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 6449 *lr = rank; 6450 } 6451 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 6452 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 6453 PetscFunctionReturn(0); 6454 } 6455 6456 /*@ 6457 DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 6458 6459 Input Parameters: 6460 + dm - The DMPlex 6461 - label - The DMLabel 6462 6463 Output Parameter: 6464 . val - The label value field 6465 6466 Options Database Keys: 6467 . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 6468 6469 Level: intermediate 6470 6471 .seealso: DMView() 6472 @*/ 6473 PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 6474 { 6475 DM rdm; 6476 PetscFE fe; 6477 PetscScalar *v; 6478 PetscInt dim, cStart, cEnd, c; 6479 PetscErrorCode ierr; 6480 6481 PetscFunctionBeginUser; 6482 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6483 PetscValidPointer(label, 2); 6484 PetscValidPointer(val, 3); 6485 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 6486 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 6487 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 6488 ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 6489 ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 6490 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 6491 ierr = DMCreateDS(rdm);CHKERRQ(ierr); 6492 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6493 ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 6494 ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 6495 ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 6496 for (c = cStart; c < cEnd; ++c) { 6497 PetscScalar *lv; 6498 PetscInt cval; 6499 6500 ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 6501 ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 6502 *lv = cval; 6503 } 6504 ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 6505 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 6506 PetscFunctionReturn(0); 6507 } 6508 6509 /*@ 6510 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 6511 6512 Input Parameter: 6513 . dm - The DMPlex object 6514 6515 Note: This is a useful diagnostic when creating meshes programmatically. 6516 6517 Level: developer 6518 6519 .seealso: DMCreate(), DMPlexCheckSkeleton(), DMPlexCheckFaces() 6520 @*/ 6521 PetscErrorCode DMPlexCheckSymmetry(DM dm) 6522 { 6523 PetscSection coneSection, supportSection; 6524 const PetscInt *cone, *support; 6525 PetscInt coneSize, c, supportSize, s; 6526 PetscInt pStart, pEnd, p, pp, csize, ssize; 6527 PetscBool storagecheck = PETSC_TRUE; 6528 PetscErrorCode ierr; 6529 6530 PetscFunctionBegin; 6531 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6532 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 6533 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 6534 /* Check that point p is found in the support of its cone points, and vice versa */ 6535 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6536 for (p = pStart; p < pEnd; ++p) { 6537 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 6538 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 6539 for (c = 0; c < coneSize; ++c) { 6540 PetscBool dup = PETSC_FALSE; 6541 PetscInt d; 6542 for (d = c-1; d >= 0; --d) { 6543 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 6544 } 6545 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 6546 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 6547 for (s = 0; s < supportSize; ++s) { 6548 if (support[s] == p) break; 6549 } 6550 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 6551 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 6552 for (s = 0; s < coneSize; ++s) { 6553 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 6554 } 6555 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6556 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 6557 for (s = 0; s < supportSize; ++s) { 6558 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 6559 } 6560 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6561 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 6562 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 6563 } 6564 } 6565 ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 6566 if (p != pp) { storagecheck = PETSC_FALSE; continue; } 6567 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 6568 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 6569 for (s = 0; s < supportSize; ++s) { 6570 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6571 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6572 for (c = 0; c < coneSize; ++c) { 6573 ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 6574 if (cone[c] != pp) { c = 0; break; } 6575 if (cone[c] == p) break; 6576 } 6577 if (c >= coneSize) { 6578 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 6579 for (c = 0; c < supportSize; ++c) { 6580 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 6581 } 6582 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6583 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 6584 for (c = 0; c < coneSize; ++c) { 6585 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 6586 } 6587 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6588 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 6589 } 6590 } 6591 } 6592 if (storagecheck) { 6593 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 6594 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 6595 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 6596 } 6597 PetscFunctionReturn(0); 6598 } 6599 6600 /*@ 6601 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 6602 6603 Input Parameters: 6604 + dm - The DMPlex object 6605 - cellHeight - Normally 0 6606 6607 Note: This is a useful diagnostic when creating meshes programmatically. 6608 Currently applicable only to homogeneous simplex or tensor meshes. 6609 6610 Level: developer 6611 6612 .seealso: DMCreate(), DMPlexCheckSymmetry(), DMPlexCheckFaces() 6613 @*/ 6614 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 6615 { 6616 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 6617 PetscBool isSimplex = PETSC_FALSE; 6618 PetscErrorCode ierr; 6619 6620 PetscFunctionBegin; 6621 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6622 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6623 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 6624 if (cStart < cEnd) { 6625 ierr = DMPlexGetConeSize(dm, cStart, &c);CHKERRQ(ierr); 6626 isSimplex = c == dim+1 ? PETSC_TRUE : PETSC_FALSE; 6627 } 6628 switch (dim) { 6629 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 6630 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 6631 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 6632 default: 6633 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %D", dim); 6634 } 6635 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6636 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 6637 cMax = cMax >= 0 ? cMax : cEnd; 6638 for (c = cStart; c < cMax; ++c) { 6639 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 6640 6641 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6642 for (cl = 0; cl < closureSize*2; cl += 2) { 6643 const PetscInt p = closure[cl]; 6644 if ((p >= vStart) && (p < vEnd)) ++coneSize; 6645 } 6646 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6647 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has %D vertices != %D", c, coneSize, numCorners); 6648 } 6649 for (c = cMax; c < cEnd; ++c) { 6650 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 6651 6652 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6653 for (cl = 0; cl < closureSize*2; cl += 2) { 6654 const PetscInt p = closure[cl]; 6655 if ((p >= vStart) && (p < vEnd)) ++coneSize; 6656 } 6657 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6658 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %D has %D vertices > %D", c, coneSize, numHybridCorners); 6659 } 6660 PetscFunctionReturn(0); 6661 } 6662 6663 /*@ 6664 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 6665 6666 Input Parameters: 6667 + dm - The DMPlex object 6668 - cellHeight - Normally 0 6669 6670 Note: This is a useful diagnostic when creating meshes programmatically. 6671 6672 Level: developer 6673 6674 .seealso: DMCreate(), DMPlexCheckSymmetry(), DMPlexCheckSkeleton() 6675 @*/ 6676 PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 6677 { 6678 PetscInt pMax[4]; 6679 PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 6680 PetscErrorCode ierr; 6681 6682 PetscFunctionBegin; 6683 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6684 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6685 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6686 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6687 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 6688 for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 6689 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 6690 for (c = cStart; c < cEnd; ++c) { 6691 const PetscInt *cone, *ornt, *faces; 6692 PetscInt numFaces, faceSize, coneSize,f; 6693 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 6694 6695 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 6696 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 6697 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6698 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6699 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6700 for (cl = 0; cl < closureSize*2; cl += 2) { 6701 const PetscInt p = closure[cl]; 6702 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 6703 } 6704 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 6705 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has %D faces but should have %D", c, coneSize, numFaces); 6706 for (f = 0; f < numFaces; ++f) { 6707 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 6708 6709 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 6710 for (cl = 0; cl < fclosureSize*2; cl += 2) { 6711 const PetscInt p = fclosure[cl]; 6712 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 6713 } 6714 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); 6715 for (v = 0; v < fnumCorners; ++v) { 6716 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]); 6717 } 6718 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 6719 } 6720 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 6721 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6722 } 6723 } 6724 PetscFunctionReturn(0); 6725 } 6726 6727 /*@ 6728 DMPlexCheckGeometry - Check the geometry of mesh cells 6729 6730 Input Parameter: 6731 . dm - The DMPlex object 6732 6733 Note: This is a useful diagnostic when creating meshes programmatically. 6734 6735 Level: developer 6736 6737 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton(), DMCheckFaces() 6738 @*/ 6739 PetscErrorCode DMPlexCheckGeometry(DM dm) 6740 { 6741 PetscReal detJ, J[9], refVol = 1.0; 6742 PetscReal vol; 6743 PetscInt dim, depth, d, cStart, cEnd, c; 6744 PetscErrorCode ierr; 6745 6746 PetscFunctionBegin; 6747 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6748 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6749 for (d = 0; d < dim; ++d) refVol *= 2.0; 6750 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6751 for (c = cStart; c < cEnd; ++c) { 6752 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 6753 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted, |J| = %g", c, (double) detJ); 6754 ierr = PetscInfo2(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 6755 if (depth > 1) { 6756 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 6757 if (vol <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %d is inverted, vol = %g", c, (double) vol); 6758 ierr = PetscInfo2(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 6759 } 6760 } 6761 PetscFunctionReturn(0); 6762 } 6763 6764 static PetscErrorCode DMPlexAreAllConePointsInArray_Private(DM dm, PetscInt p, PetscInt npoints, const PetscInt *points, PetscInt *missingPoint) 6765 { 6766 PetscInt i,l,n; 6767 const PetscInt *cone; 6768 PetscErrorCode ierr; 6769 6770 PetscFunctionBegin; 6771 *missingPoint = -1; 6772 ierr = DMPlexGetConeSize(dm, p, &n);CHKERRQ(ierr); 6773 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 6774 for (i=0; i<n; i++) { 6775 ierr = PetscFindInt(cone[i], npoints, points, &l);CHKERRQ(ierr); 6776 if (l < 0) { 6777 *missingPoint = cone[i]; 6778 break; 6779 } 6780 } 6781 PetscFunctionReturn(0); 6782 } 6783 6784 /*@ 6785 DMPlexCheckPointSF - Check that several sufficient conditions are met for the point SF of this plex. 6786 6787 Input Parameters: 6788 . dm - The DMPlex object 6789 6790 Note: This is mainly intended for debugging/testing purposes. 6791 6792 Level: developer 6793 6794 .seealso: DMGetPointSF(), DMPlexCheckSymmetry(), DMPlexCheckSkeleton(), DMPlexCheckFaces() 6795 @*/ 6796 PetscErrorCode DMPlexCheckPointSF(DM dm) 6797 { 6798 PetscSF sf; 6799 PetscInt d,depth,i,nleaves,p,plo,phi,missingPoint; 6800 const PetscInt *locals; 6801 PetscErrorCode ierr; 6802 6803 PetscFunctionBegin; 6804 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6805 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6806 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6807 ierr = PetscSFGetGraph(sf, NULL, &nleaves, &locals, NULL);CHKERRQ(ierr); 6808 6809 /* 1) check there are no faces in 2D, cells in 3D, in interface */ 6810 ierr = DMPlexGetVTKCellHeight(dm, &d);CHKERRQ(ierr); 6811 ierr = DMPlexGetHeightStratum(dm, d, &plo, &phi);CHKERRQ(ierr); 6812 for (i=0; i<nleaves; i++) { 6813 p = locals[i]; 6814 if (p >= plo && p < phi) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "point SF contains %d which is a cell",p); 6815 } 6816 6817 /* 2) if some point is in interface, then all its cone points must be also in interface */ 6818 for (i=0; i<nleaves; i++) { 6819 p = locals[i]; 6820 ierr = DMPlexAreAllConePointsInArray_Private(dm, p, nleaves, locals, &missingPoint);CHKERRQ(ierr); 6821 if (missingPoint >= 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "point SF contains %d but not %d from its cone",p,missingPoint); 6822 } 6823 PetscFunctionReturn(0); 6824 } 6825 6826 typedef struct cell_stats 6827 { 6828 PetscReal min, max, sum, squaresum; 6829 PetscInt count; 6830 } cell_stats_t; 6831 6832 static void cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 6833 { 6834 PetscInt i, N = *len; 6835 6836 for (i = 0; i < N; i++) { 6837 cell_stats_t *A = (cell_stats_t *) a; 6838 cell_stats_t *B = (cell_stats_t *) b; 6839 6840 B->min = PetscMin(A->min,B->min); 6841 B->max = PetscMax(A->max,B->max); 6842 B->sum += A->sum; 6843 B->squaresum += A->squaresum; 6844 B->count += A->count; 6845 } 6846 } 6847 6848 /*@ 6849 DMPlexCheckCellShape - Checks the Jacobian of the mapping and computes some minimal statistics. 6850 6851 Input Parameters: 6852 + dm - The DMPlex object 6853 - output - If true, statistics will be displayed on stdout 6854 6855 Note: This is mainly intended for debugging/testing purposes. 6856 6857 Level: developer 6858 6859 .seealso: DMPlexCheckSymmetry(), DMPlexCheckSkeleton(), DMPlexCheckFaces() 6860 @*/ 6861 PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output) 6862 { 6863 PetscMPIInt rank,size; 6864 PetscInt dim, c, cStart, cEnd, cMax, count = 0; 6865 cell_stats_t stats, globalStats; 6866 PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 6867 MPI_Comm comm = PetscObjectComm((PetscObject)dm); 6868 DM dmCoarse; 6869 PetscErrorCode ierr; 6870 6871 PetscFunctionBegin; 6872 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6873 stats.min = PETSC_MAX_REAL; 6874 stats.max = PETSC_MIN_REAL; 6875 stats.sum = stats.squaresum = 0.; 6876 stats.count = 0; 6877 6878 ierr = DMGetCoordinateDim(dm,&dim);CHKERRQ(ierr); 6879 ierr = PetscMalloc2(dim * dim, &J, dim * dim, &invJ);CHKERRQ(ierr); 6880 ierr = DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 6881 ierr = DMPlexGetHybridBounds(dm,&cMax,NULL,NULL,NULL);CHKERRQ(ierr); 6882 cMax = cMax < 0 ? cEnd : cMax; 6883 for (c = cStart; c < cMax; c++) { 6884 PetscInt i; 6885 PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 6886 6887 ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 6888 if (detJ < 0.0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 6889 for (i = 0; i < dim * dim; i++) { 6890 frobJ += J[i] * J[i]; 6891 frobInvJ += invJ[i] * invJ[i]; 6892 } 6893 cond2 = frobJ * frobInvJ; 6894 cond = PetscSqrtReal(cond2); 6895 6896 stats.min = PetscMin(stats.min,cond); 6897 stats.max = PetscMax(stats.max,cond); 6898 stats.sum += cond; 6899 stats.squaresum += cond2; 6900 stats.count++; 6901 } 6902 6903 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 6904 if (size > 1) { 6905 PetscMPIInt blockLengths[2] = {4,1}; 6906 MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 6907 MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 6908 MPI_Op statReduce; 6909 6910 ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRQ(ierr); 6911 ierr = MPI_Type_commit(&statType);CHKERRQ(ierr); 6912 ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRQ(ierr); 6913 ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRQ(ierr); 6914 ierr = MPI_Op_free(&statReduce);CHKERRQ(ierr); 6915 ierr = MPI_Type_free(&statType);CHKERRQ(ierr); 6916 } else { 6917 ierr = PetscMemcpy(&globalStats,&stats,sizeof(stats));CHKERRQ(ierr); 6918 } 6919 6920 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 6921 if (!rank) { 6922 count = globalStats.count; 6923 min = globalStats.min; 6924 max = globalStats.max; 6925 mean = globalStats.sum / globalStats.count; 6926 stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 6927 } 6928 6929 if (output) { 6930 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); 6931 } 6932 ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 6933 6934 ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 6935 if (dmCoarse) { 6936 PetscBool isplex; 6937 6938 ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 6939 if (isplex) { 6940 ierr = DMPlexCheckCellShape(dmCoarse,output);CHKERRQ(ierr); 6941 } 6942 } 6943 PetscFunctionReturn(0); 6944 } 6945 6946 /* Pointwise interpolation 6947 Just code FEM for now 6948 u^f = I u^c 6949 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 6950 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 6951 I_{ij} = psi^f_i phi^c_j 6952 */ 6953 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 6954 { 6955 PetscSection gsc, gsf; 6956 PetscInt m, n; 6957 void *ctx; 6958 DM cdm; 6959 PetscBool regular, ismatis; 6960 PetscErrorCode ierr; 6961 6962 PetscFunctionBegin; 6963 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 6964 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 6965 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 6966 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 6967 6968 ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 6969 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 6970 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6971 ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 6972 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 6973 6974 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 6975 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 6976 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 6977 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 6978 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 6979 if (scaling) { 6980 /* Use naive scaling */ 6981 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 6982 } 6983 PetscFunctionReturn(0); 6984 } 6985 6986 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 6987 { 6988 PetscErrorCode ierr; 6989 VecScatter ctx; 6990 6991 PetscFunctionBegin; 6992 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 6993 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 6994 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 6995 PetscFunctionReturn(0); 6996 } 6997 6998 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 6999 { 7000 PetscSection gsc, gsf; 7001 PetscInt m, n; 7002 void *ctx; 7003 DM cdm; 7004 PetscBool regular; 7005 PetscErrorCode ierr; 7006 7007 PetscFunctionBegin; 7008 ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 7009 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 7010 ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 7011 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 7012 7013 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 7014 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 7015 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 7016 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 7017 7018 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 7019 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 7020 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 7021 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 7022 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 7023 PetscFunctionReturn(0); 7024 } 7025 7026 /*@ 7027 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 7028 7029 Input Parameter: 7030 . dm - The DMPlex object 7031 7032 Output Parameter: 7033 . regular - The flag 7034 7035 Level: intermediate 7036 7037 .seealso: DMPlexSetRegularRefinement() 7038 @*/ 7039 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 7040 { 7041 PetscFunctionBegin; 7042 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7043 PetscValidPointer(regular, 2); 7044 *regular = ((DM_Plex *) dm->data)->regularRefinement; 7045 PetscFunctionReturn(0); 7046 } 7047 7048 /*@ 7049 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 7050 7051 Input Parameters: 7052 + dm - The DMPlex object 7053 - regular - The flag 7054 7055 Level: intermediate 7056 7057 .seealso: DMPlexGetRegularRefinement() 7058 @*/ 7059 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 7060 { 7061 PetscFunctionBegin; 7062 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7063 ((DM_Plex *) dm->data)->regularRefinement = regular; 7064 PetscFunctionReturn(0); 7065 } 7066 7067 /* anchors */ 7068 /*@ 7069 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 7070 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 7071 7072 not collective 7073 7074 Input Parameters: 7075 . dm - The DMPlex object 7076 7077 Output Parameters: 7078 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 7079 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 7080 7081 7082 Level: intermediate 7083 7084 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 7085 @*/ 7086 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 7087 { 7088 DM_Plex *plex = (DM_Plex *)dm->data; 7089 PetscErrorCode ierr; 7090 7091 PetscFunctionBegin; 7092 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7093 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 7094 if (anchorSection) *anchorSection = plex->anchorSection; 7095 if (anchorIS) *anchorIS = plex->anchorIS; 7096 PetscFunctionReturn(0); 7097 } 7098 7099 /*@ 7100 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 7101 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 7102 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 7103 7104 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 7105 DMGetConstraints() and filling in the entries in the constraint matrix. 7106 7107 collective on dm 7108 7109 Input Parameters: 7110 + dm - The DMPlex object 7111 . 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). 7112 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 7113 7114 The reference counts of anchorSection and anchorIS are incremented. 7115 7116 Level: intermediate 7117 7118 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 7119 @*/ 7120 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 7121 { 7122 DM_Plex *plex = (DM_Plex *)dm->data; 7123 PetscMPIInt result; 7124 PetscErrorCode ierr; 7125 7126 PetscFunctionBegin; 7127 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7128 if (anchorSection) { 7129 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 7130 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 7131 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 7132 } 7133 if (anchorIS) { 7134 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 7135 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 7136 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 7137 } 7138 7139 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 7140 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 7141 plex->anchorSection = anchorSection; 7142 7143 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 7144 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 7145 plex->anchorIS = anchorIS; 7146 7147 #if defined(PETSC_USE_DEBUG) 7148 if (anchorIS && anchorSection) { 7149 PetscInt size, a, pStart, pEnd; 7150 const PetscInt *anchors; 7151 7152 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 7153 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 7154 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 7155 for (a = 0; a < size; a++) { 7156 PetscInt p; 7157 7158 p = anchors[a]; 7159 if (p >= pStart && p < pEnd) { 7160 PetscInt dof; 7161 7162 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 7163 if (dof) { 7164 PetscErrorCode ierr2; 7165 7166 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 7167 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 7168 } 7169 } 7170 } 7171 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 7172 } 7173 #endif 7174 /* reset the generic constraints */ 7175 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 7176 PetscFunctionReturn(0); 7177 } 7178 7179 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 7180 { 7181 PetscSection anchorSection; 7182 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 7183 PetscErrorCode ierr; 7184 7185 PetscFunctionBegin; 7186 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7187 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 7188 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 7189 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 7190 if (numFields) { 7191 PetscInt f; 7192 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 7193 7194 for (f = 0; f < numFields; f++) { 7195 PetscInt numComp; 7196 7197 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 7198 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 7199 } 7200 } 7201 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 7202 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 7203 pStart = PetscMax(pStart,sStart); 7204 pEnd = PetscMin(pEnd,sEnd); 7205 pEnd = PetscMax(pStart,pEnd); 7206 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 7207 for (p = pStart; p < pEnd; p++) { 7208 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 7209 if (dof) { 7210 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 7211 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 7212 for (f = 0; f < numFields; f++) { 7213 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 7214 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 7215 } 7216 } 7217 } 7218 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 7219 PetscFunctionReturn(0); 7220 } 7221 7222 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 7223 { 7224 PetscSection aSec; 7225 PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 7226 const PetscInt *anchors; 7227 PetscInt numFields, f; 7228 IS aIS; 7229 PetscErrorCode ierr; 7230 7231 PetscFunctionBegin; 7232 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7233 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 7234 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 7235 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 7236 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 7237 ierr = MatSetType(*cMat,MATSEQAIJ);CHKERRQ(ierr); 7238 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 7239 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 7240 /* cSec will be a subset of aSec and section */ 7241 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 7242 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 7243 i[0] = 0; 7244 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 7245 for (p = pStart; p < pEnd; p++) { 7246 PetscInt rDof, rOff, r; 7247 7248 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 7249 if (!rDof) continue; 7250 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 7251 if (numFields) { 7252 for (f = 0; f < numFields; f++) { 7253 annz = 0; 7254 for (r = 0; r < rDof; r++) { 7255 a = anchors[rOff + r]; 7256 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 7257 annz += aDof; 7258 } 7259 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 7260 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 7261 for (q = 0; q < dof; q++) { 7262 i[off + q + 1] = i[off + q] + annz; 7263 } 7264 } 7265 } 7266 else { 7267 annz = 0; 7268 for (q = 0; q < dof; q++) { 7269 a = anchors[off + q]; 7270 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 7271 annz += aDof; 7272 } 7273 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 7274 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 7275 for (q = 0; q < dof; q++) { 7276 i[off + q + 1] = i[off + q] + annz; 7277 } 7278 } 7279 } 7280 nnz = i[m]; 7281 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 7282 offset = 0; 7283 for (p = pStart; p < pEnd; p++) { 7284 if (numFields) { 7285 for (f = 0; f < numFields; f++) { 7286 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 7287 for (q = 0; q < dof; q++) { 7288 PetscInt rDof, rOff, r; 7289 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 7290 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 7291 for (r = 0; r < rDof; r++) { 7292 PetscInt s; 7293 7294 a = anchors[rOff + r]; 7295 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 7296 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 7297 for (s = 0; s < aDof; s++) { 7298 j[offset++] = aOff + s; 7299 } 7300 } 7301 } 7302 } 7303 } 7304 else { 7305 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 7306 for (q = 0; q < dof; q++) { 7307 PetscInt rDof, rOff, r; 7308 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 7309 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 7310 for (r = 0; r < rDof; r++) { 7311 PetscInt s; 7312 7313 a = anchors[rOff + r]; 7314 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 7315 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 7316 for (s = 0; s < aDof; s++) { 7317 j[offset++] = aOff + s; 7318 } 7319 } 7320 } 7321 } 7322 } 7323 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 7324 ierr = PetscFree(i);CHKERRQ(ierr); 7325 ierr = PetscFree(j);CHKERRQ(ierr); 7326 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7327 PetscFunctionReturn(0); 7328 } 7329 7330 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 7331 { 7332 DM_Plex *plex = (DM_Plex *)dm->data; 7333 PetscSection anchorSection, section, cSec; 7334 Mat cMat; 7335 PetscErrorCode ierr; 7336 7337 PetscFunctionBegin; 7338 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7339 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 7340 if (anchorSection) { 7341 PetscInt Nf; 7342 7343 ierr = DMGetSection(dm,§ion);CHKERRQ(ierr); 7344 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 7345 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 7346 ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 7347 if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 7348 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 7349 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 7350 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 7351 } 7352 PetscFunctionReturn(0); 7353 } 7354 7355 PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 7356 { 7357 IS subis; 7358 PetscSection section, subsection; 7359 PetscErrorCode ierr; 7360 7361 PetscFunctionBegin; 7362 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7363 if (!section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 7364 if (!subdm) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 7365 /* Create subdomain */ 7366 ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 7367 /* Create submodel */ 7368 ierr = DMPlexCreateSubpointIS(*subdm, &subis);CHKERRQ(ierr); 7369 ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 7370 ierr = ISDestroy(&subis);CHKERRQ(ierr); 7371 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 7372 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 7373 ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 7374 /* Create map from submodel to global model */ 7375 if (is) { 7376 PetscSection sectionGlobal, subsectionGlobal; 7377 IS spIS; 7378 const PetscInt *spmap; 7379 PetscInt *subIndices; 7380 PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 7381 PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 7382 7383 ierr = DMPlexCreateSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 7384 ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 7385 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 7386 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 7387 ierr = DMGetDefaultGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 7388 ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 7389 for (p = pStart; p < pEnd; ++p) { 7390 PetscInt gdof, pSubSize = 0; 7391 7392 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 7393 if (gdof > 0) { 7394 for (f = 0; f < Nf; ++f) { 7395 PetscInt fdof, fcdof; 7396 7397 ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 7398 ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 7399 pSubSize += fdof-fcdof; 7400 } 7401 subSize += pSubSize; 7402 if (pSubSize) { 7403 if (bs < 0) { 7404 bs = pSubSize; 7405 } else if (bs != pSubSize) { 7406 /* Layout does not admit a pointwise block size */ 7407 bs = 1; 7408 } 7409 } 7410 } 7411 } 7412 /* Must have same blocksize on all procs (some might have no points) */ 7413 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 7414 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 7415 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 7416 else {bs = bsMinMax[0];} 7417 ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 7418 for (p = pStart; p < pEnd; ++p) { 7419 PetscInt gdof, goff; 7420 7421 ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 7422 if (gdof > 0) { 7423 const PetscInt point = spmap[p]; 7424 7425 ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 7426 for (f = 0; f < Nf; ++f) { 7427 PetscInt fdof, fcdof, fc, f2, poff = 0; 7428 7429 /* Can get rid of this loop by storing field information in the global section */ 7430 for (f2 = 0; f2 < f; ++f2) { 7431 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 7432 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 7433 poff += fdof-fcdof; 7434 } 7435 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7436 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7437 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 7438 subIndices[subOff] = goff+poff+fc; 7439 } 7440 } 7441 } 7442 } 7443 ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 7444 ierr = ISDestroy(&spIS);CHKERRQ(ierr); 7445 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 7446 if (bs > 1) { 7447 /* We need to check that the block size does not come from non-contiguous fields */ 7448 PetscInt i, j, set = 1; 7449 for (i = 0; i < subSize; i += bs) { 7450 for (j = 0; j < bs; ++j) { 7451 if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 7452 } 7453 } 7454 if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 7455 } 7456 /* Attach nullspace */ 7457 for (f = 0; f < Nf; ++f) { 7458 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 7459 if ((*subdm)->nullspaceConstructors[f]) break; 7460 } 7461 if (f < Nf) { 7462 MatNullSpace nullSpace; 7463 7464 ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, &nullSpace);CHKERRQ(ierr); 7465 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 7466 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 7467 } 7468 } 7469 PetscFunctionReturn(0); 7470 } 7471