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