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