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