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