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