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