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