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