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