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