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