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