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