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