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