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