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