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: numDof[f*(dim+1)+d] gives the number of dof for field f on points of dimension d. For instance, numDof[1] is the 3455 number of dof for field 0 on each edge. 3456 3457 The chart permutation is the same one set using PetscSectionSetPermutation() 3458 3459 Level: developer 3460 3461 Fortran Notes: 3462 A Fortran 90 version is available as DMPlexCreateSectionF90() 3463 3464 .keywords: mesh, elements 3465 .seealso: DMPlexCreate(), PetscSectionCreate(), PetscSectionSetPermutation() 3466 @*/ 3467 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) 3468 { 3469 PetscSection aSec; 3470 PetscErrorCode ierr; 3471 3472 PetscFunctionBegin; 3473 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 3474 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3475 if (perm) {ierr = PetscSectionSetPermutation(*section, perm);CHKERRQ(ierr);} 3476 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3477 ierr = DMPlexGetAnchors(dm,&aSec,NULL);CHKERRQ(ierr); 3478 if (numBC || aSec) { 3479 ierr = DMPlexCreateSectionBCIndicesField(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3480 ierr = DMPlexCreateSectionBCIndices(dm, *section);CHKERRQ(ierr); 3481 } 3482 ierr = PetscSectionViewFromOptions(*section,NULL,"-section_view");CHKERRQ(ierr); 3483 PetscFunctionReturn(0); 3484 } 3485 3486 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 3487 { 3488 PetscSection section, s; 3489 Mat m; 3490 PetscInt maxHeight; 3491 PetscErrorCode ierr; 3492 3493 PetscFunctionBegin; 3494 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 3495 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 3496 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 3497 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 3498 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 3499 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 3500 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 3501 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 3502 ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr); 3503 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 3504 ierr = MatDestroy(&m);CHKERRQ(ierr); 3505 PetscFunctionReturn(0); 3506 } 3507 3508 PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 3509 { 3510 Vec coordsLocal; 3511 DM coordsDM; 3512 PetscErrorCode ierr; 3513 3514 PetscFunctionBegin; 3515 *field = NULL; 3516 ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr); 3517 ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr); 3518 if (coordsLocal && coordsDM) { 3519 ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr); 3520 } 3521 PetscFunctionReturn(0); 3522 } 3523 3524 /*@C 3525 DMPlexGetConeSection - Return a section which describes the layout of cone data 3526 3527 Not Collective 3528 3529 Input Parameters: 3530 . dm - The DMPlex object 3531 3532 Output Parameter: 3533 . section - The PetscSection object 3534 3535 Level: developer 3536 3537 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 3538 @*/ 3539 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 3540 { 3541 DM_Plex *mesh = (DM_Plex*) dm->data; 3542 3543 PetscFunctionBegin; 3544 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3545 if (section) *section = mesh->coneSection; 3546 PetscFunctionReturn(0); 3547 } 3548 3549 /*@C 3550 DMPlexGetSupportSection - Return a section which describes the layout of support data 3551 3552 Not Collective 3553 3554 Input Parameters: 3555 . dm - The DMPlex object 3556 3557 Output Parameter: 3558 . section - The PetscSection object 3559 3560 Level: developer 3561 3562 .seealso: DMPlexGetConeSection() 3563 @*/ 3564 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 3565 { 3566 DM_Plex *mesh = (DM_Plex*) dm->data; 3567 3568 PetscFunctionBegin; 3569 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3570 if (section) *section = mesh->supportSection; 3571 PetscFunctionReturn(0); 3572 } 3573 3574 /*@C 3575 DMPlexGetCones - Return cone data 3576 3577 Not Collective 3578 3579 Input Parameters: 3580 . dm - The DMPlex object 3581 3582 Output Parameter: 3583 . cones - The cone for each point 3584 3585 Level: developer 3586 3587 .seealso: DMPlexGetConeSection() 3588 @*/ 3589 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 3590 { 3591 DM_Plex *mesh = (DM_Plex*) dm->data; 3592 3593 PetscFunctionBegin; 3594 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3595 if (cones) *cones = mesh->cones; 3596 PetscFunctionReturn(0); 3597 } 3598 3599 /*@C 3600 DMPlexGetConeOrientations - Return cone orientation data 3601 3602 Not Collective 3603 3604 Input Parameters: 3605 . dm - The DMPlex object 3606 3607 Output Parameter: 3608 . coneOrientations - The cone orientation for each point 3609 3610 Level: developer 3611 3612 .seealso: DMPlexGetConeSection() 3613 @*/ 3614 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 3615 { 3616 DM_Plex *mesh = (DM_Plex*) dm->data; 3617 3618 PetscFunctionBegin; 3619 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3620 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 3621 PetscFunctionReturn(0); 3622 } 3623 3624 /******************************** FEM Support **********************************/ 3625 3626 PetscErrorCode DMPlexCreateSpectralClosurePermutation(DM dm, PetscInt point, PetscSection section) 3627 { 3628 DMLabel label; 3629 PetscInt *perm; 3630 PetscInt dim, depth, eStart, k, Nf, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 3631 PetscErrorCode ierr; 3632 3633 PetscFunctionBegin; 3634 if (point < 0) {ierr = DMPlexGetDepthStratum(dm, 1, &point, NULL);CHKERRQ(ierr);} 3635 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3636 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3637 ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); 3638 if (depth == 1) {eStart = point;} 3639 else if (depth == dim) { 3640 const PetscInt *cone; 3641 3642 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3643 eStart = cone[0]; 3644 } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering", point, depth); 3645 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3646 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 3647 if (dim <= 1) PetscFunctionReturn(0); 3648 for (f = 0; f < Nf; ++f) { 3649 /* An order k SEM disc has k-1 dofs on an edge */ 3650 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3651 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3652 k = k/Nc + 1; 3653 size += PetscPowInt(k+1, dim)*Nc; 3654 } 3655 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 3656 for (f = 0; f < Nf; ++f) { 3657 switch (dim) { 3658 case 2: 3659 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 3660 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3661 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3662 k = k/Nc + 1; 3663 /* The SEM order is 3664 3665 v_lb, {e_b}, v_rb, 3666 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 3667 v_lt, reverse {e_t}, v_rt 3668 */ 3669 { 3670 const PetscInt of = 0; 3671 const PetscInt oeb = of + PetscSqr(k-1); 3672 const PetscInt oer = oeb + (k-1); 3673 const PetscInt oet = oer + (k-1); 3674 const PetscInt oel = oet + (k-1); 3675 const PetscInt ovlb = oel + (k-1); 3676 const PetscInt ovrb = ovlb + 1; 3677 const PetscInt ovrt = ovrb + 1; 3678 const PetscInt ovlt = ovrt + 1; 3679 PetscInt o; 3680 3681 /* bottom */ 3682 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 3683 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3684 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 3685 /* middle */ 3686 for (i = 0; i < k-1; ++i) { 3687 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 3688 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; 3689 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 3690 } 3691 /* top */ 3692 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 3693 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3694 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 3695 foffset = offset; 3696 } 3697 break; 3698 case 3: 3699 /* The original hex closure is 3700 3701 {c, 3702 f_b, f_t, f_f, f_b, f_r, f_l, 3703 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 3704 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 3705 */ 3706 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3707 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3708 k = k/Nc + 1; 3709 /* The SEM order is 3710 Bottom Slice 3711 v_blf, {e^{(k-1)-n}_bf}, v_brf, 3712 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 3713 v_blb, {e_bb}, v_brb, 3714 3715 Middle Slice (j) 3716 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 3717 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 3718 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 3719 3720 Top Slice 3721 v_tlf, {e_tf}, v_trf, 3722 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 3723 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 3724 */ 3725 { 3726 const PetscInt oc = 0; 3727 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 3728 const PetscInt oft = ofb + PetscSqr(k-1); 3729 const PetscInt off = oft + PetscSqr(k-1); 3730 const PetscInt ofk = off + PetscSqr(k-1); 3731 const PetscInt ofr = ofk + PetscSqr(k-1); 3732 const PetscInt ofl = ofr + PetscSqr(k-1); 3733 const PetscInt oebl = ofl + PetscSqr(k-1); 3734 const PetscInt oebb = oebl + (k-1); 3735 const PetscInt oebr = oebb + (k-1); 3736 const PetscInt oebf = oebr + (k-1); 3737 const PetscInt oetf = oebf + (k-1); 3738 const PetscInt oetr = oetf + (k-1); 3739 const PetscInt oetb = oetr + (k-1); 3740 const PetscInt oetl = oetb + (k-1); 3741 const PetscInt oerf = oetl + (k-1); 3742 const PetscInt oelf = oerf + (k-1); 3743 const PetscInt oelb = oelf + (k-1); 3744 const PetscInt oerb = oelb + (k-1); 3745 const PetscInt ovblf = oerb + (k-1); 3746 const PetscInt ovblb = ovblf + 1; 3747 const PetscInt ovbrb = ovblb + 1; 3748 const PetscInt ovbrf = ovbrb + 1; 3749 const PetscInt ovtlf = ovbrf + 1; 3750 const PetscInt ovtrf = ovtlf + 1; 3751 const PetscInt ovtrb = ovtrf + 1; 3752 const PetscInt ovtlb = ovtrb + 1; 3753 PetscInt o, n; 3754 3755 /* Bottom Slice */ 3756 /* bottom */ 3757 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 3758 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3759 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 3760 /* middle */ 3761 for (i = 0; i < k-1; ++i) { 3762 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 3763 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;} 3764 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 3765 } 3766 /* top */ 3767 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 3768 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3769 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 3770 3771 /* Middle Slice */ 3772 for (j = 0; j < k-1; ++j) { 3773 /* bottom */ 3774 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 3775 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; 3776 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 3777 /* middle */ 3778 for (i = 0; i < k-1; ++i) { 3779 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 3780 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; 3781 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 3782 } 3783 /* top */ 3784 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 3785 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; 3786 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 3787 } 3788 3789 /* Top Slice */ 3790 /* bottom */ 3791 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 3792 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3793 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 3794 /* middle */ 3795 for (i = 0; i < k-1; ++i) { 3796 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 3797 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 3798 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 3799 } 3800 /* top */ 3801 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 3802 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3803 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 3804 3805 foffset = offset; 3806 } 3807 break; 3808 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", dim); 3809 } 3810 } 3811 if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 3812 /* Check permutation */ 3813 { 3814 PetscInt *check; 3815 3816 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 3817 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]);} 3818 for (i = 0; i < size; ++i) check[perm[i]] = i; 3819 for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 3820 ierr = PetscFree(check);CHKERRQ(ierr); 3821 } 3822 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 3823 PetscFunctionReturn(0); 3824 } 3825 3826 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 3827 { 3828 PetscDS prob; 3829 PetscInt depth, Nf, h; 3830 DMLabel label; 3831 PetscErrorCode ierr; 3832 3833 PetscFunctionBeginHot; 3834 prob = dm->prob; 3835 Nf = prob->Nf; 3836 label = dm->depthLabel; 3837 *dspace = NULL; 3838 if (field < Nf) { 3839 PetscObject disc = prob->disc[field]; 3840 3841 if (disc->classid == PETSCFE_CLASSID) { 3842 PetscDualSpace dsp; 3843 3844 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 3845 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 3846 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 3847 h = depth - 1 - h; 3848 if (h) { 3849 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 3850 } else { 3851 *dspace = dsp; 3852 } 3853 } 3854 } 3855 PetscFunctionReturn(0); 3856 } 3857 3858 3859 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3860 { 3861 PetscScalar *array, *vArray; 3862 const PetscInt *cone, *coneO; 3863 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 3864 PetscErrorCode ierr; 3865 3866 PetscFunctionBeginHot; 3867 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3868 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3869 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3870 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3871 if (!values || !*values) { 3872 if ((point >= pStart) && (point < pEnd)) { 3873 PetscInt dof; 3874 3875 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3876 size += dof; 3877 } 3878 for (p = 0; p < numPoints; ++p) { 3879 const PetscInt cp = cone[p]; 3880 PetscInt dof; 3881 3882 if ((cp < pStart) || (cp >= pEnd)) continue; 3883 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3884 size += dof; 3885 } 3886 if (!values) { 3887 if (csize) *csize = size; 3888 PetscFunctionReturn(0); 3889 } 3890 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 3891 } else { 3892 array = *values; 3893 } 3894 size = 0; 3895 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3896 if ((point >= pStart) && (point < pEnd)) { 3897 PetscInt dof, off, d; 3898 PetscScalar *varr; 3899 3900 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3901 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3902 varr = &vArray[off]; 3903 for (d = 0; d < dof; ++d, ++offset) { 3904 array[offset] = varr[d]; 3905 } 3906 size += dof; 3907 } 3908 for (p = 0; p < numPoints; ++p) { 3909 const PetscInt cp = cone[p]; 3910 PetscInt o = coneO[p]; 3911 PetscInt dof, off, d; 3912 PetscScalar *varr; 3913 3914 if ((cp < pStart) || (cp >= pEnd)) continue; 3915 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3916 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 3917 varr = &vArray[off]; 3918 if (o >= 0) { 3919 for (d = 0; d < dof; ++d, ++offset) { 3920 array[offset] = varr[d]; 3921 } 3922 } else { 3923 for (d = dof-1; d >= 0; --d, ++offset) { 3924 array[offset] = varr[d]; 3925 } 3926 } 3927 size += dof; 3928 } 3929 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3930 if (!*values) { 3931 if (csize) *csize = size; 3932 *values = array; 3933 } else { 3934 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 3935 *csize = size; 3936 } 3937 PetscFunctionReturn(0); 3938 } 3939 3940 static PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 3941 { 3942 const PetscInt *cla; 3943 PetscInt np, *pts = NULL; 3944 PetscErrorCode ierr; 3945 3946 PetscFunctionBeginHot; 3947 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 3948 if (!*clPoints) { 3949 PetscInt pStart, pEnd, p, q; 3950 3951 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3952 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 3953 /* Compress out points not in the section */ 3954 for (p = 0, q = 0; p < np; p++) { 3955 PetscInt r = pts[2*p]; 3956 if ((r >= pStart) && (r < pEnd)) { 3957 pts[q*2] = r; 3958 pts[q*2+1] = pts[2*p+1]; 3959 ++q; 3960 } 3961 } 3962 np = q; 3963 cla = NULL; 3964 } else { 3965 PetscInt dof, off; 3966 3967 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 3968 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 3969 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 3970 np = dof/2; 3971 pts = (PetscInt *) &cla[off]; 3972 } 3973 *numPoints = np; 3974 *points = pts; 3975 *clp = cla; 3976 3977 PetscFunctionReturn(0); 3978 } 3979 3980 static PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 3981 { 3982 PetscErrorCode ierr; 3983 3984 PetscFunctionBeginHot; 3985 if (!*clPoints) { 3986 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 3987 } else { 3988 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 3989 } 3990 *numPoints = 0; 3991 *points = NULL; 3992 *clSec = NULL; 3993 *clPoints = NULL; 3994 *clp = NULL; 3995 PetscFunctionReturn(0); 3996 } 3997 3998 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[]) 3999 { 4000 PetscInt offset = 0, p; 4001 const PetscInt **perms = NULL; 4002 const PetscScalar **flips = NULL; 4003 PetscErrorCode ierr; 4004 4005 PetscFunctionBeginHot; 4006 *size = 0; 4007 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4008 for (p = 0; p < numPoints; p++) { 4009 const PetscInt point = points[2*p]; 4010 const PetscInt *perm = perms ? perms[p] : NULL; 4011 const PetscScalar *flip = flips ? flips[p] : NULL; 4012 PetscInt dof, off, d; 4013 const PetscScalar *varr; 4014 4015 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4016 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4017 varr = &vArray[off]; 4018 if (clperm) { 4019 if (perm) { 4020 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 4021 } else { 4022 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 4023 } 4024 if (flip) { 4025 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 4026 } 4027 } else { 4028 if (perm) { 4029 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 4030 } else { 4031 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 4032 } 4033 if (flip) { 4034 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 4035 } 4036 } 4037 offset += dof; 4038 } 4039 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4040 *size = offset; 4041 PetscFunctionReturn(0); 4042 } 4043 4044 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[]) 4045 { 4046 PetscInt offset = 0, f; 4047 PetscErrorCode ierr; 4048 4049 PetscFunctionBeginHot; 4050 *size = 0; 4051 for (f = 0; f < numFields; ++f) { 4052 PetscInt p; 4053 const PetscInt **perms = NULL; 4054 const PetscScalar **flips = NULL; 4055 4056 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4057 for (p = 0; p < numPoints; p++) { 4058 const PetscInt point = points[2*p]; 4059 PetscInt fdof, foff, b; 4060 const PetscScalar *varr; 4061 const PetscInt *perm = perms ? perms[p] : NULL; 4062 const PetscScalar *flip = flips ? flips[p] : NULL; 4063 4064 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4065 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4066 varr = &vArray[foff]; 4067 if (clperm) { 4068 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 4069 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 4070 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 4071 } else { 4072 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 4073 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 4074 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 4075 } 4076 offset += fdof; 4077 } 4078 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4079 } 4080 *size = offset; 4081 PetscFunctionReturn(0); 4082 } 4083 4084 /*@C 4085 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 4086 4087 Not collective 4088 4089 Input Parameters: 4090 + dm - The DM 4091 . section - The section describing the layout in v, or NULL to use the default section 4092 . v - The local vector 4093 . point - The point in the DM 4094 . csize - The size of the input values array, or NULL 4095 - values - An array to use for the values, or NULL to have it allocated automatically 4096 4097 Output Parameters: 4098 + csize - The number of values in the closure 4099 - values - The array of values. If the user provided NULL, it is a borrowed array and should not be freed 4100 4101 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 4102 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 4103 $ assembly function, and a user may already have allocated storage for this operation. 4104 $ 4105 $ A typical use could be 4106 $ 4107 $ values = NULL; 4108 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4109 $ for (cl = 0; cl < clSize; ++cl) { 4110 $ <Compute on closure> 4111 $ } 4112 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4113 $ 4114 $ or 4115 $ 4116 $ PetscMalloc1(clMaxSize, &values); 4117 $ for (p = pStart; p < pEnd; ++p) { 4118 $ clSize = clMaxSize; 4119 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4120 $ for (cl = 0; cl < clSize; ++cl) { 4121 $ <Compute on closure> 4122 $ } 4123 $ } 4124 $ PetscFree(values); 4125 4126 Fortran Notes: 4127 Since it returns an array, this routine is only available in Fortran 90, and you must 4128 include petsc.h90 in your code. 4129 4130 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4131 4132 Level: intermediate 4133 4134 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4135 @*/ 4136 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4137 { 4138 PetscSection clSection; 4139 IS clPoints; 4140 PetscScalar *array; 4141 const PetscScalar *vArray; 4142 PetscInt *points = NULL; 4143 const PetscInt *clp, *perm; 4144 PetscInt depth, numFields, numPoints, size; 4145 PetscErrorCode ierr; 4146 4147 PetscFunctionBeginHot; 4148 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4149 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4150 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4151 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4152 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4153 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4154 if (depth == 1 && numFields < 2) { 4155 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 4156 PetscFunctionReturn(0); 4157 } 4158 /* Get points */ 4159 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4160 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &perm);CHKERRQ(ierr); 4161 /* Get array */ 4162 if (!values || !*values) { 4163 PetscInt asize = 0, dof, p; 4164 4165 for (p = 0; p < numPoints*2; p += 2) { 4166 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4167 asize += dof; 4168 } 4169 if (!values) { 4170 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4171 if (csize) *csize = asize; 4172 PetscFunctionReturn(0); 4173 } 4174 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 4175 } else { 4176 array = *values; 4177 } 4178 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 4179 /* Get values */ 4180 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 4181 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, array);CHKERRQ(ierr);} 4182 /* Cleanup points */ 4183 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4184 /* Cleanup array */ 4185 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 4186 if (!*values) { 4187 if (csize) *csize = size; 4188 *values = array; 4189 } else { 4190 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 4191 *csize = size; 4192 } 4193 PetscFunctionReturn(0); 4194 } 4195 4196 /*@C 4197 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 4198 4199 Not collective 4200 4201 Input Parameters: 4202 + dm - The DM 4203 . section - The section describing the layout in v, or NULL to use the default section 4204 . v - The local vector 4205 . point - The point in the DM 4206 . csize - The number of values in the closure, or NULL 4207 - values - The array of values, which is a borrowed array and should not be freed 4208 4209 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 4210 4211 Fortran Notes: 4212 Since it returns an array, this routine is only available in Fortran 90, and you must 4213 include petsc.h90 in your code. 4214 4215 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4216 4217 Level: intermediate 4218 4219 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4220 @*/ 4221 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4222 { 4223 PetscInt size = 0; 4224 PetscErrorCode ierr; 4225 4226 PetscFunctionBegin; 4227 /* Should work without recalculating size */ 4228 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 4229 *values = NULL; 4230 PetscFunctionReturn(0); 4231 } 4232 4233 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 4234 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 4235 4236 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[]) 4237 { 4238 PetscInt cdof; /* The number of constraints on this point */ 4239 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4240 PetscScalar *a; 4241 PetscInt off, cind = 0, k; 4242 PetscErrorCode ierr; 4243 4244 PetscFunctionBegin; 4245 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4246 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4247 a = &array[off]; 4248 if (!cdof || setBC) { 4249 if (clperm) { 4250 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 4251 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 4252 } else { 4253 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 4254 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 4255 } 4256 } else { 4257 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4258 if (clperm) { 4259 if (perm) {for (k = 0; k < dof; ++k) { 4260 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4261 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 4262 } 4263 } else { 4264 for (k = 0; k < dof; ++k) { 4265 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4266 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 4267 } 4268 } 4269 } else { 4270 if (perm) { 4271 for (k = 0; k < dof; ++k) { 4272 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4273 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 4274 } 4275 } else { 4276 for (k = 0; k < dof; ++k) { 4277 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4278 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 4279 } 4280 } 4281 } 4282 } 4283 PetscFunctionReturn(0); 4284 } 4285 4286 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[]) 4287 { 4288 PetscInt cdof; /* The number of constraints on this point */ 4289 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4290 PetscScalar *a; 4291 PetscInt off, cind = 0, k; 4292 PetscErrorCode ierr; 4293 4294 PetscFunctionBegin; 4295 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4296 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4297 a = &array[off]; 4298 if (cdof) { 4299 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4300 if (clperm) { 4301 if (perm) { 4302 for (k = 0; k < dof; ++k) { 4303 if ((cind < cdof) && (k == cdofs[cind])) { 4304 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 4305 cind++; 4306 } 4307 } 4308 } else { 4309 for (k = 0; k < dof; ++k) { 4310 if ((cind < cdof) && (k == cdofs[cind])) { 4311 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 4312 cind++; 4313 } 4314 } 4315 } 4316 } else { 4317 if (perm) { 4318 for (k = 0; k < dof; ++k) { 4319 if ((cind < cdof) && (k == cdofs[cind])) { 4320 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 4321 cind++; 4322 } 4323 } 4324 } else { 4325 for (k = 0; k < dof; ++k) { 4326 if ((cind < cdof) && (k == cdofs[cind])) { 4327 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 4328 cind++; 4329 } 4330 } 4331 } 4332 } 4333 } 4334 PetscFunctionReturn(0); 4335 } 4336 4337 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[]) 4338 { 4339 PetscScalar *a; 4340 PetscInt fdof, foff, fcdof, foffset = *offset; 4341 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4342 PetscInt cind = 0, b; 4343 PetscErrorCode ierr; 4344 4345 PetscFunctionBegin; 4346 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4347 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 4348 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4349 a = &array[foff]; 4350 if (!fcdof || setBC) { 4351 if (clperm) { 4352 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 4353 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 4354 } else { 4355 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 4356 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 4357 } 4358 } else { 4359 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4360 if (clperm) { 4361 if (perm) { 4362 for (b = 0; b < fdof; b++) { 4363 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4364 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 4365 } 4366 } else { 4367 for (b = 0; b < fdof; b++) { 4368 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4369 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 4370 } 4371 } 4372 } else { 4373 if (perm) { 4374 for (b = 0; b < fdof; b++) { 4375 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4376 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 4377 } 4378 } else { 4379 for (b = 0; b < fdof; b++) { 4380 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4381 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 4382 } 4383 } 4384 } 4385 } 4386 *offset += fdof; 4387 PetscFunctionReturn(0); 4388 } 4389 4390 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[]) 4391 { 4392 PetscScalar *a; 4393 PetscInt fdof, foff, fcdof, foffset = *offset; 4394 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4395 PetscInt cind = 0, ncind = 0, b; 4396 PetscBool ncSet, fcSet; 4397 PetscErrorCode ierr; 4398 4399 PetscFunctionBegin; 4400 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4401 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 4402 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4403 a = &array[foff]; 4404 if (fcdof) { 4405 /* We just override fcdof and fcdofs with Ncc and comps */ 4406 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4407 if (clperm) { 4408 if (perm) { 4409 if (comps) { 4410 for (b = 0; b < fdof; b++) { 4411 ncSet = fcSet = PETSC_FALSE; 4412 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4413 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4414 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 4415 } 4416 } else { 4417 for (b = 0; b < fdof; b++) { 4418 if ((cind < fcdof) && (b == fcdofs[cind])) { 4419 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 4420 ++cind; 4421 } 4422 } 4423 } 4424 } else { 4425 if (comps) { 4426 for (b = 0; b < fdof; b++) { 4427 ncSet = fcSet = PETSC_FALSE; 4428 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4429 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4430 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 4431 } 4432 } else { 4433 for (b = 0; b < fdof; b++) { 4434 if ((cind < fcdof) && (b == fcdofs[cind])) { 4435 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 4436 ++cind; 4437 } 4438 } 4439 } 4440 } 4441 } else { 4442 if (perm) { 4443 if (comps) { 4444 for (b = 0; b < fdof; b++) { 4445 ncSet = fcSet = PETSC_FALSE; 4446 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4447 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4448 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 4449 } 4450 } else { 4451 for (b = 0; b < fdof; b++) { 4452 if ((cind < fcdof) && (b == fcdofs[cind])) { 4453 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 4454 ++cind; 4455 } 4456 } 4457 } 4458 } else { 4459 if (comps) { 4460 for (b = 0; b < fdof; b++) { 4461 ncSet = fcSet = PETSC_FALSE; 4462 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4463 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4464 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 4465 } 4466 } else { 4467 for (b = 0; b < fdof; b++) { 4468 if ((cind < fcdof) && (b == fcdofs[cind])) { 4469 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 4470 ++cind; 4471 } 4472 } 4473 } 4474 } 4475 } 4476 } 4477 *offset += fdof; 4478 PetscFunctionReturn(0); 4479 } 4480 4481 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4482 { 4483 PetscScalar *array; 4484 const PetscInt *cone, *coneO; 4485 PetscInt pStart, pEnd, p, numPoints, off, dof; 4486 PetscErrorCode ierr; 4487 4488 PetscFunctionBeginHot; 4489 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4490 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 4491 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4492 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 4493 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4494 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 4495 const PetscInt cp = !p ? point : cone[p-1]; 4496 const PetscInt o = !p ? 0 : coneO[p-1]; 4497 4498 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 4499 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4500 /* ADD_VALUES */ 4501 { 4502 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4503 PetscScalar *a; 4504 PetscInt cdof, coff, cind = 0, k; 4505 4506 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 4507 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 4508 a = &array[coff]; 4509 if (!cdof) { 4510 if (o >= 0) { 4511 for (k = 0; k < dof; ++k) { 4512 a[k] += values[off+k]; 4513 } 4514 } else { 4515 for (k = 0; k < dof; ++k) { 4516 a[k] += values[off+dof-k-1]; 4517 } 4518 } 4519 } else { 4520 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 4521 if (o >= 0) { 4522 for (k = 0; k < dof; ++k) { 4523 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4524 a[k] += values[off+k]; 4525 } 4526 } else { 4527 for (k = 0; k < dof; ++k) { 4528 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4529 a[k] += values[off+dof-k-1]; 4530 } 4531 } 4532 } 4533 } 4534 } 4535 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4536 PetscFunctionReturn(0); 4537 } 4538 4539 /*@C 4540 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 4541 4542 Not collective 4543 4544 Input Parameters: 4545 + dm - The DM 4546 . section - The section describing the layout in v, or NULL to use the default section 4547 . v - The local vector 4548 . point - The point in the DM 4549 . values - The array of values 4550 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 4551 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 4552 4553 Fortran Notes: 4554 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4555 4556 Level: intermediate 4557 4558 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 4559 @*/ 4560 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4561 { 4562 PetscSection clSection; 4563 IS clPoints; 4564 PetscScalar *array; 4565 PetscInt *points = NULL; 4566 const PetscInt *clp, *clperm; 4567 PetscInt depth, numFields, numPoints, p; 4568 PetscErrorCode ierr; 4569 4570 PetscFunctionBeginHot; 4571 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4572 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4573 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4574 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4575 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4576 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4577 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 4578 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 4579 PetscFunctionReturn(0); 4580 } 4581 /* Get points */ 4582 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 4583 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4584 /* Get array */ 4585 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4586 /* Get values */ 4587 if (numFields > 0) { 4588 PetscInt offset = 0, f; 4589 for (f = 0; f < numFields; ++f) { 4590 const PetscInt **perms = NULL; 4591 const PetscScalar **flips = NULL; 4592 4593 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4594 switch (mode) { 4595 case INSERT_VALUES: 4596 for (p = 0; p < numPoints; p++) { 4597 const PetscInt point = points[2*p]; 4598 const PetscInt *perm = perms ? perms[p] : NULL; 4599 const PetscScalar *flip = flips ? flips[p] : NULL; 4600 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 4601 } break; 4602 case INSERT_ALL_VALUES: 4603 for (p = 0; p < numPoints; p++) { 4604 const PetscInt point = points[2*p]; 4605 const PetscInt *perm = perms ? perms[p] : NULL; 4606 const PetscScalar *flip = flips ? flips[p] : NULL; 4607 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 4608 } break; 4609 case INSERT_BC_VALUES: 4610 for (p = 0; p < numPoints; p++) { 4611 const PetscInt point = points[2*p]; 4612 const PetscInt *perm = perms ? perms[p] : NULL; 4613 const PetscScalar *flip = flips ? flips[p] : NULL; 4614 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 4615 } break; 4616 case ADD_VALUES: 4617 for (p = 0; p < numPoints; p++) { 4618 const PetscInt point = points[2*p]; 4619 const PetscInt *perm = perms ? perms[p] : NULL; 4620 const PetscScalar *flip = flips ? flips[p] : NULL; 4621 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 4622 } break; 4623 case ADD_ALL_VALUES: 4624 for (p = 0; p < numPoints; p++) { 4625 const PetscInt point = points[2*p]; 4626 const PetscInt *perm = perms ? perms[p] : NULL; 4627 const PetscScalar *flip = flips ? flips[p] : NULL; 4628 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 4629 } break; 4630 case ADD_BC_VALUES: 4631 for (p = 0; p < numPoints; p++) { 4632 const PetscInt point = points[2*p]; 4633 const PetscInt *perm = perms ? perms[p] : NULL; 4634 const PetscScalar *flip = flips ? flips[p] : NULL; 4635 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 4636 } break; 4637 default: 4638 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4639 } 4640 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4641 } 4642 } else { 4643 PetscInt dof, off; 4644 const PetscInt **perms = NULL; 4645 const PetscScalar **flips = NULL; 4646 4647 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4648 switch (mode) { 4649 case INSERT_VALUES: 4650 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4651 const PetscInt point = points[2*p]; 4652 const PetscInt *perm = perms ? perms[p] : NULL; 4653 const PetscScalar *flip = flips ? flips[p] : NULL; 4654 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4655 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 4656 } break; 4657 case INSERT_ALL_VALUES: 4658 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4659 const PetscInt point = points[2*p]; 4660 const PetscInt *perm = perms ? perms[p] : NULL; 4661 const PetscScalar *flip = flips ? flips[p] : NULL; 4662 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4663 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 4664 } break; 4665 case INSERT_BC_VALUES: 4666 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4667 const PetscInt point = points[2*p]; 4668 const PetscInt *perm = perms ? perms[p] : NULL; 4669 const PetscScalar *flip = flips ? flips[p] : NULL; 4670 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4671 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 4672 } break; 4673 case ADD_VALUES: 4674 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4675 const PetscInt point = points[2*p]; 4676 const PetscInt *perm = perms ? perms[p] : NULL; 4677 const PetscScalar *flip = flips ? flips[p] : NULL; 4678 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4679 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 4680 } break; 4681 case ADD_ALL_VALUES: 4682 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4683 const PetscInt point = points[2*p]; 4684 const PetscInt *perm = perms ? perms[p] : NULL; 4685 const PetscScalar *flip = flips ? flips[p] : NULL; 4686 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4687 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 4688 } break; 4689 case ADD_BC_VALUES: 4690 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4691 const PetscInt point = points[2*p]; 4692 const PetscInt *perm = perms ? perms[p] : NULL; 4693 const PetscScalar *flip = flips ? flips[p] : NULL; 4694 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4695 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 4696 } break; 4697 default: 4698 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4699 } 4700 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4701 } 4702 /* Cleanup points */ 4703 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4704 /* Cleanup array */ 4705 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4706 PetscFunctionReturn(0); 4707 } 4708 4709 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, PetscInt Ncc, const PetscInt comps[], const PetscScalar values[], InsertMode mode) 4710 { 4711 PetscSection clSection; 4712 IS clPoints; 4713 PetscScalar *array; 4714 PetscInt *points = NULL; 4715 const PetscInt *clp, *clperm; 4716 PetscInt numFields, numPoints, p; 4717 PetscInt offset = 0, f; 4718 PetscErrorCode ierr; 4719 4720 PetscFunctionBeginHot; 4721 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4722 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4723 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4724 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4725 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4726 /* Get points */ 4727 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 4728 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4729 /* Get array */ 4730 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4731 /* Get values */ 4732 for (f = 0; f < numFields; ++f) { 4733 const PetscInt **perms = NULL; 4734 const PetscScalar **flips = NULL; 4735 4736 if (!fieldActive[f]) { 4737 for (p = 0; p < numPoints*2; p += 2) { 4738 PetscInt fdof; 4739 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4740 offset += fdof; 4741 } 4742 continue; 4743 } 4744 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4745 switch (mode) { 4746 case INSERT_VALUES: 4747 for (p = 0; p < numPoints; p++) { 4748 const PetscInt point = points[2*p]; 4749 const PetscInt *perm = perms ? perms[p] : NULL; 4750 const PetscScalar *flip = flips ? flips[p] : NULL; 4751 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 4752 } break; 4753 case INSERT_ALL_VALUES: 4754 for (p = 0; p < numPoints; p++) { 4755 const PetscInt point = points[2*p]; 4756 const PetscInt *perm = perms ? perms[p] : NULL; 4757 const PetscScalar *flip = flips ? flips[p] : NULL; 4758 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 4759 } break; 4760 case INSERT_BC_VALUES: 4761 for (p = 0; p < numPoints; p++) { 4762 const PetscInt point = points[2*p]; 4763 const PetscInt *perm = perms ? perms[p] : NULL; 4764 const PetscScalar *flip = flips ? flips[p] : NULL; 4765 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, clperm, values, &offset, array); 4766 } break; 4767 case ADD_VALUES: 4768 for (p = 0; p < numPoints; p++) { 4769 const PetscInt point = points[2*p]; 4770 const PetscInt *perm = perms ? perms[p] : NULL; 4771 const PetscScalar *flip = flips ? flips[p] : NULL; 4772 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 4773 } break; 4774 case ADD_ALL_VALUES: 4775 for (p = 0; p < numPoints; p++) { 4776 const PetscInt point = points[2*p]; 4777 const PetscInt *perm = perms ? perms[p] : NULL; 4778 const PetscScalar *flip = flips ? flips[p] : NULL; 4779 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 4780 } break; 4781 default: 4782 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4783 } 4784 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4785 } 4786 /* Cleanup points */ 4787 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4788 /* Cleanup array */ 4789 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4790 PetscFunctionReturn(0); 4791 } 4792 4793 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 4794 { 4795 PetscMPIInt rank; 4796 PetscInt i, j; 4797 PetscErrorCode ierr; 4798 4799 PetscFunctionBegin; 4800 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 4801 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 4802 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 4803 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 4804 numCIndices = numCIndices ? numCIndices : numRIndices; 4805 for (i = 0; i < numRIndices; i++) { 4806 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 4807 for (j = 0; j < numCIndices; j++) { 4808 #if defined(PETSC_USE_COMPLEX) 4809 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 4810 #else 4811 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 4812 #endif 4813 } 4814 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 4815 } 4816 PetscFunctionReturn(0); 4817 } 4818 4819 /* . off - The global offset of this point */ 4820 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], PetscInt indices[]) 4821 { 4822 PetscInt dof; /* The number of unknowns on this point */ 4823 PetscInt cdof; /* The number of constraints on this point */ 4824 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4825 PetscInt cind = 0, k; 4826 PetscErrorCode ierr; 4827 4828 PetscFunctionBegin; 4829 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4830 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4831 if (!cdof || setBC) { 4832 if (perm) { 4833 for (k = 0; k < dof; k++) indices[*loff+perm[k]] = off + k; 4834 } else { 4835 for (k = 0; k < dof; k++) indices[*loff+k] = off + k; 4836 } 4837 } else { 4838 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4839 if (perm) { 4840 for (k = 0; k < dof; ++k) { 4841 if ((cind < cdof) && (k == cdofs[cind])) { 4842 /* Insert check for returning constrained indices */ 4843 indices[*loff+perm[k]] = -(off+k+1); 4844 ++cind; 4845 } else { 4846 indices[*loff+perm[k]] = off+k-cind; 4847 } 4848 } 4849 } else { 4850 for (k = 0; k < dof; ++k) { 4851 if ((cind < cdof) && (k == cdofs[cind])) { 4852 /* Insert check for returning constrained indices */ 4853 indices[*loff+k] = -(off+k+1); 4854 ++cind; 4855 } else { 4856 indices[*loff+k] = off+k-cind; 4857 } 4858 } 4859 } 4860 } 4861 *loff += dof; 4862 PetscFunctionReturn(0); 4863 } 4864 4865 /* . off - The global offset of this point */ 4866 PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, PetscInt indices[]) 4867 { 4868 PetscInt numFields, foff, f; 4869 PetscErrorCode ierr; 4870 4871 PetscFunctionBegin; 4872 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4873 for (f = 0, foff = 0; f < numFields; ++f) { 4874 PetscInt fdof, cfdof; 4875 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4876 PetscInt cind = 0, b; 4877 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 4878 4879 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4880 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 4881 if (!cfdof || setBC) { 4882 if (perm) {for (b = 0; b < fdof; b++) {indices[foffs[f]+perm[b]] = off+foff+b;}} 4883 else {for (b = 0; b < fdof; b++) {indices[foffs[f]+ b ] = off+foff+b;}} 4884 } else { 4885 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4886 if (perm) { 4887 for (b = 0; b < fdof; b++) { 4888 if ((cind < cfdof) && (b == fcdofs[cind])) { 4889 indices[foffs[f]+perm[b]] = -(off+foff+b+1); 4890 ++cind; 4891 } else { 4892 indices[foffs[f]+perm[b]] = off+foff+b-cind; 4893 } 4894 } 4895 } else { 4896 for (b = 0; b < fdof; b++) { 4897 if ((cind < cfdof) && (b == fcdofs[cind])) { 4898 indices[foffs[f]+b] = -(off+foff+b+1); 4899 ++cind; 4900 } else { 4901 indices[foffs[f]+b] = off+foff+b-cind; 4902 } 4903 } 4904 } 4905 } 4906 foff += (setBC ? fdof : (fdof - cfdof)); 4907 foffs[f] += fdof; 4908 } 4909 PetscFunctionReturn(0); 4910 } 4911 4912 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) 4913 { 4914 Mat cMat; 4915 PetscSection aSec, cSec; 4916 IS aIS; 4917 PetscInt aStart = -1, aEnd = -1; 4918 const PetscInt *anchors; 4919 PetscInt numFields, f, p, q, newP = 0; 4920 PetscInt newNumPoints = 0, newNumIndices = 0; 4921 PetscInt *newPoints, *indices, *newIndices; 4922 PetscInt maxAnchor, maxDof; 4923 PetscInt newOffsets[32]; 4924 PetscInt *pointMatOffsets[32]; 4925 PetscInt *newPointOffsets[32]; 4926 PetscScalar *pointMat[32]; 4927 PetscScalar *newValues=NULL,*tmpValues; 4928 PetscBool anyConstrained = PETSC_FALSE; 4929 PetscErrorCode ierr; 4930 4931 PetscFunctionBegin; 4932 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4933 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4934 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4935 4936 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 4937 /* if there are point-to-point constraints */ 4938 if (aSec) { 4939 ierr = PetscMemzero(newOffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4940 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 4941 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 4942 /* figure out how many points are going to be in the new element matrix 4943 * (we allow double counting, because it's all just going to be summed 4944 * into the global matrix anyway) */ 4945 for (p = 0; p < 2*numPoints; p+=2) { 4946 PetscInt b = points[p]; 4947 PetscInt bDof = 0, bSecDof; 4948 4949 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4950 if (!bSecDof) { 4951 continue; 4952 } 4953 if (b >= aStart && b < aEnd) { 4954 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 4955 } 4956 if (bDof) { 4957 /* this point is constrained */ 4958 /* it is going to be replaced by its anchors */ 4959 PetscInt bOff, q; 4960 4961 anyConstrained = PETSC_TRUE; 4962 newNumPoints += bDof; 4963 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 4964 for (q = 0; q < bDof; q++) { 4965 PetscInt a = anchors[bOff + q]; 4966 PetscInt aDof; 4967 4968 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 4969 newNumIndices += aDof; 4970 for (f = 0; f < numFields; ++f) { 4971 PetscInt fDof; 4972 4973 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 4974 newOffsets[f+1] += fDof; 4975 } 4976 } 4977 } 4978 else { 4979 /* this point is not constrained */ 4980 newNumPoints++; 4981 newNumIndices += bSecDof; 4982 for (f = 0; f < numFields; ++f) { 4983 PetscInt fDof; 4984 4985 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4986 newOffsets[f+1] += fDof; 4987 } 4988 } 4989 } 4990 } 4991 if (!anyConstrained) { 4992 if (outNumPoints) *outNumPoints = 0; 4993 if (outNumIndices) *outNumIndices = 0; 4994 if (outPoints) *outPoints = NULL; 4995 if (outValues) *outValues = NULL; 4996 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 4997 PetscFunctionReturn(0); 4998 } 4999 5000 if (outNumPoints) *outNumPoints = newNumPoints; 5001 if (outNumIndices) *outNumIndices = newNumIndices; 5002 5003 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 5004 5005 if (!outPoints && !outValues) { 5006 if (offsets) { 5007 for (f = 0; f <= numFields; f++) { 5008 offsets[f] = newOffsets[f]; 5009 } 5010 } 5011 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 5012 PetscFunctionReturn(0); 5013 } 5014 5015 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 5016 5017 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 5018 5019 /* workspaces */ 5020 if (numFields) { 5021 for (f = 0; f < numFields; f++) { 5022 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 5023 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 5024 } 5025 } 5026 else { 5027 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 5028 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 5029 } 5030 5031 /* get workspaces for the point-to-point matrices */ 5032 if (numFields) { 5033 PetscInt totalOffset, totalMatOffset; 5034 5035 for (p = 0; p < numPoints; p++) { 5036 PetscInt b = points[2*p]; 5037 PetscInt bDof = 0, bSecDof; 5038 5039 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5040 if (!bSecDof) { 5041 for (f = 0; f < numFields; f++) { 5042 newPointOffsets[f][p + 1] = 0; 5043 pointMatOffsets[f][p + 1] = 0; 5044 } 5045 continue; 5046 } 5047 if (b >= aStart && b < aEnd) { 5048 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5049 } 5050 if (bDof) { 5051 for (f = 0; f < numFields; f++) { 5052 PetscInt fDof, q, bOff, allFDof = 0; 5053 5054 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5055 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5056 for (q = 0; q < bDof; q++) { 5057 PetscInt a = anchors[bOff + q]; 5058 PetscInt aFDof; 5059 5060 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 5061 allFDof += aFDof; 5062 } 5063 newPointOffsets[f][p+1] = allFDof; 5064 pointMatOffsets[f][p+1] = fDof * allFDof; 5065 } 5066 } 5067 else { 5068 for (f = 0; f < numFields; f++) { 5069 PetscInt fDof; 5070 5071 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5072 newPointOffsets[f][p+1] = fDof; 5073 pointMatOffsets[f][p+1] = 0; 5074 } 5075 } 5076 } 5077 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 5078 newPointOffsets[f][0] = totalOffset; 5079 pointMatOffsets[f][0] = totalMatOffset; 5080 for (p = 0; p < numPoints; p++) { 5081 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 5082 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 5083 } 5084 totalOffset = newPointOffsets[f][numPoints]; 5085 totalMatOffset = pointMatOffsets[f][numPoints]; 5086 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 5087 } 5088 } 5089 else { 5090 for (p = 0; p < numPoints; p++) { 5091 PetscInt b = points[2*p]; 5092 PetscInt bDof = 0, bSecDof; 5093 5094 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5095 if (!bSecDof) { 5096 newPointOffsets[0][p + 1] = 0; 5097 pointMatOffsets[0][p + 1] = 0; 5098 continue; 5099 } 5100 if (b >= aStart && b < aEnd) { 5101 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5102 } 5103 if (bDof) { 5104 PetscInt bOff, q, allDof = 0; 5105 5106 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5107 for (q = 0; q < bDof; q++) { 5108 PetscInt a = anchors[bOff + q], aDof; 5109 5110 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 5111 allDof += aDof; 5112 } 5113 newPointOffsets[0][p+1] = allDof; 5114 pointMatOffsets[0][p+1] = bSecDof * allDof; 5115 } 5116 else { 5117 newPointOffsets[0][p+1] = bSecDof; 5118 pointMatOffsets[0][p+1] = 0; 5119 } 5120 } 5121 newPointOffsets[0][0] = 0; 5122 pointMatOffsets[0][0] = 0; 5123 for (p = 0; p < numPoints; p++) { 5124 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 5125 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 5126 } 5127 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 5128 } 5129 5130 /* output arrays */ 5131 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5132 5133 /* get the point-to-point matrices; construct newPoints */ 5134 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 5135 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 5136 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 5137 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 5138 if (numFields) { 5139 for (p = 0, newP = 0; p < numPoints; p++) { 5140 PetscInt b = points[2*p]; 5141 PetscInt o = points[2*p+1]; 5142 PetscInt bDof = 0, bSecDof; 5143 5144 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 5145 if (!bSecDof) { 5146 continue; 5147 } 5148 if (b >= aStart && b < aEnd) { 5149 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5150 } 5151 if (bDof) { 5152 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 5153 5154 fStart[0] = 0; 5155 fEnd[0] = 0; 5156 for (f = 0; f < numFields; f++) { 5157 PetscInt fDof; 5158 5159 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 5160 fStart[f+1] = fStart[f] + fDof; 5161 fEnd[f+1] = fStart[f+1]; 5162 } 5163 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 5164 ierr = DMPlexGetIndicesPointFields_Internal(cSec, b, bOff, fEnd, PETSC_TRUE, perms, p, indices);CHKERRQ(ierr); 5165 5166 fAnchorStart[0] = 0; 5167 fAnchorEnd[0] = 0; 5168 for (f = 0; f < numFields; f++) { 5169 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 5170 5171 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 5172 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 5173 } 5174 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5175 for (q = 0; q < bDof; q++) { 5176 PetscInt a = anchors[bOff + q], aOff; 5177 5178 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 5179 newPoints[2*(newP + q)] = a; 5180 newPoints[2*(newP + q) + 1] = 0; 5181 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 5182 ierr = DMPlexGetIndicesPointFields_Internal(section, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, newIndices);CHKERRQ(ierr); 5183 } 5184 newP += bDof; 5185 5186 if (outValues) { 5187 /* get the point-to-point submatrix */ 5188 for (f = 0; f < numFields; f++) { 5189 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 5190 } 5191 } 5192 } 5193 else { 5194 newPoints[2 * newP] = b; 5195 newPoints[2 * newP + 1] = o; 5196 newP++; 5197 } 5198 } 5199 } else { 5200 for (p = 0; p < numPoints; p++) { 5201 PetscInt b = points[2*p]; 5202 PetscInt o = points[2*p+1]; 5203 PetscInt bDof = 0, bSecDof; 5204 5205 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 5206 if (!bSecDof) { 5207 continue; 5208 } 5209 if (b >= aStart && b < aEnd) { 5210 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5211 } 5212 if (bDof) { 5213 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 5214 5215 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 5216 ierr = DMPlexGetIndicesPoint_Internal(cSec, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, indices);CHKERRQ(ierr); 5217 5218 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 5219 for (q = 0; q < bDof; q++) { 5220 PetscInt a = anchors[bOff + q], aOff; 5221 5222 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 5223 5224 newPoints[2*(newP + q)] = a; 5225 newPoints[2*(newP + q) + 1] = 0; 5226 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 5227 ierr = DMPlexGetIndicesPoint_Internal(section, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, newIndices);CHKERRQ(ierr); 5228 } 5229 newP += bDof; 5230 5231 /* get the point-to-point submatrix */ 5232 if (outValues) { 5233 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 5234 } 5235 } 5236 else { 5237 newPoints[2 * newP] = b; 5238 newPoints[2 * newP + 1] = o; 5239 newP++; 5240 } 5241 } 5242 } 5243 5244 if (outValues) { 5245 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 5246 ierr = PetscMemzero(tmpValues,newNumIndices*numIndices*sizeof(*tmpValues));CHKERRQ(ierr); 5247 /* multiply constraints on the right */ 5248 if (numFields) { 5249 for (f = 0; f < numFields; f++) { 5250 PetscInt oldOff = offsets[f]; 5251 5252 for (p = 0; p < numPoints; p++) { 5253 PetscInt cStart = newPointOffsets[f][p]; 5254 PetscInt b = points[2 * p]; 5255 PetscInt c, r, k; 5256 PetscInt dof; 5257 5258 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 5259 if (!dof) { 5260 continue; 5261 } 5262 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 5263 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 5264 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 5265 5266 for (r = 0; r < numIndices; r++) { 5267 for (c = 0; c < nCols; c++) { 5268 for (k = 0; k < dof; k++) { 5269 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 5270 } 5271 } 5272 } 5273 } 5274 else { 5275 /* copy this column as is */ 5276 for (r = 0; r < numIndices; r++) { 5277 for (c = 0; c < dof; c++) { 5278 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 5279 } 5280 } 5281 } 5282 oldOff += dof; 5283 } 5284 } 5285 } 5286 else { 5287 PetscInt oldOff = 0; 5288 for (p = 0; p < numPoints; p++) { 5289 PetscInt cStart = newPointOffsets[0][p]; 5290 PetscInt b = points[2 * p]; 5291 PetscInt c, r, k; 5292 PetscInt dof; 5293 5294 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 5295 if (!dof) { 5296 continue; 5297 } 5298 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 5299 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 5300 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 5301 5302 for (r = 0; r < numIndices; r++) { 5303 for (c = 0; c < nCols; c++) { 5304 for (k = 0; k < dof; k++) { 5305 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 5306 } 5307 } 5308 } 5309 } 5310 else { 5311 /* copy this column as is */ 5312 for (r = 0; r < numIndices; r++) { 5313 for (c = 0; c < dof; c++) { 5314 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 5315 } 5316 } 5317 } 5318 oldOff += dof; 5319 } 5320 } 5321 5322 if (multiplyLeft) { 5323 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 5324 ierr = PetscMemzero(newValues,newNumIndices*newNumIndices*sizeof(*newValues));CHKERRQ(ierr); 5325 /* multiply constraints transpose on the left */ 5326 if (numFields) { 5327 for (f = 0; f < numFields; f++) { 5328 PetscInt oldOff = offsets[f]; 5329 5330 for (p = 0; p < numPoints; p++) { 5331 PetscInt rStart = newPointOffsets[f][p]; 5332 PetscInt b = points[2 * p]; 5333 PetscInt c, r, k; 5334 PetscInt dof; 5335 5336 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 5337 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 5338 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 5339 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 5340 5341 for (r = 0; r < nRows; r++) { 5342 for (c = 0; c < newNumIndices; c++) { 5343 for (k = 0; k < dof; k++) { 5344 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 5345 } 5346 } 5347 } 5348 } 5349 else { 5350 /* copy this row as is */ 5351 for (r = 0; r < dof; r++) { 5352 for (c = 0; c < newNumIndices; c++) { 5353 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 5354 } 5355 } 5356 } 5357 oldOff += dof; 5358 } 5359 } 5360 } 5361 else { 5362 PetscInt oldOff = 0; 5363 5364 for (p = 0; p < numPoints; p++) { 5365 PetscInt rStart = newPointOffsets[0][p]; 5366 PetscInt b = points[2 * p]; 5367 PetscInt c, r, k; 5368 PetscInt dof; 5369 5370 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 5371 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 5372 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 5373 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 5374 5375 for (r = 0; r < nRows; r++) { 5376 for (c = 0; c < newNumIndices; c++) { 5377 for (k = 0; k < dof; k++) { 5378 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 5379 } 5380 } 5381 } 5382 } 5383 else { 5384 /* copy this row as is */ 5385 for (r = 0; r < dof; r++) { 5386 for (c = 0; c < newNumIndices; c++) { 5387 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 5388 } 5389 } 5390 } 5391 oldOff += dof; 5392 } 5393 } 5394 5395 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 5396 } 5397 else { 5398 newValues = tmpValues; 5399 } 5400 } 5401 5402 /* clean up */ 5403 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 5404 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 5405 5406 if (numFields) { 5407 for (f = 0; f < numFields; f++) { 5408 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 5409 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 5410 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 5411 } 5412 } 5413 else { 5414 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 5415 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 5416 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 5417 } 5418 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 5419 5420 /* output */ 5421 if (outPoints) { 5422 *outPoints = newPoints; 5423 } 5424 else { 5425 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5426 } 5427 if (outValues) { 5428 *outValues = newValues; 5429 } 5430 for (f = 0; f <= numFields; f++) { 5431 offsets[f] = newOffsets[f]; 5432 } 5433 PetscFunctionReturn(0); 5434 } 5435 5436 /*@C 5437 DMPlexGetClosureIndices - Get the global indices in a vector v for all points in the closure of the given point 5438 5439 Not collective 5440 5441 Input Parameters: 5442 + dm - The DM 5443 . section - The section describing the layout in v, or NULL to use the default section 5444 . globalSection - The section describing the parallel layout in v, or NULL to use the default section 5445 - point - The mesh point 5446 5447 Output parameters: 5448 + numIndices - The number of indices 5449 . indices - The indices 5450 - outOffsets - Field offset if not NULL 5451 5452 Note: Must call DMPlexRestoreClosureIndices() to free allocated memory 5453 5454 Level: advanced 5455 5456 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure() 5457 @*/ 5458 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices, PetscInt *outOffsets) 5459 { 5460 PetscSection clSection; 5461 IS clPoints; 5462 const PetscInt *clp; 5463 const PetscInt **perms[32] = {NULL}; 5464 PetscInt *points = NULL, *pointsNew; 5465 PetscInt numPoints, numPointsNew; 5466 PetscInt offsets[32]; 5467 PetscInt Nf, Nind, NindNew, off, globalOff, f, p; 5468 PetscErrorCode ierr; 5469 5470 PetscFunctionBegin; 5471 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5472 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5473 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 5474 if (numIndices) PetscValidPointer(numIndices, 4); 5475 PetscValidPointer(indices, 5); 5476 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5477 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 5478 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5479 /* Get points in closure */ 5480 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5481 /* Get number of indices and indices per field */ 5482 for (p = 0, Nind = 0; p < numPoints*2; p += 2) { 5483 PetscInt dof, fdof; 5484 5485 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5486 for (f = 0; f < Nf; ++f) { 5487 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5488 offsets[f+1] += fdof; 5489 } 5490 Nind += dof; 5491 } 5492 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 5493 if (Nf && offsets[Nf] != Nind) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Nind); 5494 if (!Nf) offsets[1] = Nind; 5495 /* Get dual space symmetries */ 5496 for (f = 0; f < PetscMax(1,Nf); f++) { 5497 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5498 else {ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5499 } 5500 /* Correct for hanging node constraints */ 5501 { 5502 ierr = DMPlexAnchorsModifyMat(dm, section, numPoints, Nind, points, perms, NULL, &numPointsNew, &NindNew, &pointsNew, NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 5503 if (numPointsNew) { 5504 for (f = 0; f < PetscMax(1,Nf); f++) { 5505 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5506 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5507 } 5508 for (f = 0; f < PetscMax(1,Nf); f++) { 5509 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section,f,numPointsNew,pointsNew,&perms[f],NULL);CHKERRQ(ierr);} 5510 else {ierr = PetscSectionGetPointSyms(section,numPointsNew,pointsNew,&perms[f],NULL);CHKERRQ(ierr);} 5511 } 5512 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5513 numPoints = numPointsNew; 5514 Nind = NindNew; 5515 points = pointsNew; 5516 } 5517 } 5518 /* Calculate indices */ 5519 ierr = DMGetWorkArray(dm, Nind, MPIU_INT, indices);CHKERRQ(ierr); 5520 if (Nf) { 5521 if (outOffsets) { 5522 PetscInt f; 5523 5524 for (f = 0; f <= Nf; f++) { 5525 outOffsets[f] = offsets[f]; 5526 } 5527 } 5528 for (p = 0; p < numPoints; p++) { 5529 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5530 DMPlexGetIndicesPointFields_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, perms, p, *indices); 5531 } 5532 } else { 5533 for (p = 0, off = 0; p < numPoints; p++) { 5534 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 5535 5536 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5537 DMPlexGetIndicesPoint_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, *indices); 5538 } 5539 } 5540 /* Cleanup points */ 5541 for (f = 0; f < PetscMax(1,Nf); f++) { 5542 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5543 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5544 } 5545 if (numPointsNew) { 5546 ierr = DMRestoreWorkArray(dm, 2*numPointsNew, MPIU_INT, &pointsNew);CHKERRQ(ierr); 5547 } else { 5548 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5549 } 5550 if (numIndices) *numIndices = Nind; 5551 PetscFunctionReturn(0); 5552 } 5553 5554 /*@C 5555 DMPlexRestoreClosureIndices - Restore the indices in a vector v for all points in the closure of the given point 5556 5557 Not collective 5558 5559 Input Parameters: 5560 + dm - The DM 5561 . section - The section describing the layout in v, or NULL to use the default section 5562 . globalSection - The section describing the parallel layout in v, or NULL to use the default section 5563 . point - The mesh point 5564 . numIndices - The number of indices 5565 . indices - The indices 5566 - outOffsets - Field offset if not NULL 5567 5568 Level: advanced 5569 5570 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure() 5571 @*/ 5572 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices,PetscInt *outOffsets) 5573 { 5574 PetscErrorCode ierr; 5575 5576 PetscFunctionBegin; 5577 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5578 PetscValidPointer(indices, 5); 5579 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 5580 PetscFunctionReturn(0); 5581 } 5582 5583 /*@C 5584 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 5585 5586 Not collective 5587 5588 Input Parameters: 5589 + dm - The DM 5590 . section - The section describing the layout in v, or NULL to use the default section 5591 . globalSection - The section describing the layout in v, or NULL to use the default global section 5592 . A - The matrix 5593 . point - The point in the DM 5594 . values - The array of values 5595 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 5596 5597 Fortran Notes: 5598 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 5599 5600 Level: intermediate 5601 5602 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 5603 @*/ 5604 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5605 { 5606 DM_Plex *mesh = (DM_Plex*) dm->data; 5607 PetscSection clSection; 5608 IS clPoints; 5609 PetscInt *points = NULL, *newPoints; 5610 const PetscInt *clp; 5611 PetscInt *indices; 5612 PetscInt offsets[32]; 5613 const PetscInt **perms[32] = {NULL}; 5614 const PetscScalar **flips[32] = {NULL}; 5615 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, p, f; 5616 PetscScalar *valCopy = NULL; 5617 PetscScalar *newValues; 5618 PetscErrorCode ierr; 5619 5620 PetscFunctionBegin; 5621 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5622 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 5623 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5624 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 5625 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 5626 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 5627 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5628 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5629 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5630 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5631 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 5632 PetscInt fdof; 5633 5634 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5635 for (f = 0; f < numFields; ++f) { 5636 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5637 offsets[f+1] += fdof; 5638 } 5639 numIndices += dof; 5640 } 5641 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 5642 5643 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[numFields], numIndices); 5644 /* Get symmetries */ 5645 for (f = 0; f < PetscMax(1,numFields); f++) { 5646 if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5647 else {ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5648 if (values && flips[f]) { /* may need to apply sign changes to the element matrix */ 5649 PetscInt foffset = offsets[f]; 5650 5651 for (p = 0; p < numPoints; p++) { 5652 PetscInt point = points[2*p], fdof; 5653 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 5654 5655 if (!numFields) { 5656 ierr = PetscSectionGetDof(section,point,&fdof);CHKERRQ(ierr); 5657 } else { 5658 ierr = PetscSectionGetFieldDof(section,point,f,&fdof);CHKERRQ(ierr); 5659 } 5660 if (flip) { 5661 PetscInt i, j, k; 5662 5663 if (!valCopy) { 5664 ierr = DMGetWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 5665 for (j = 0; j < numIndices * numIndices; j++) valCopy[j] = values[j]; 5666 values = valCopy; 5667 } 5668 for (i = 0; i < fdof; i++) { 5669 PetscScalar fval = flip[i]; 5670 5671 for (k = 0; k < numIndices; k++) { 5672 valCopy[numIndices * (foffset + i) + k] *= fval; 5673 valCopy[numIndices * k + (foffset + i)] *= fval; 5674 } 5675 } 5676 } 5677 foffset += fdof; 5678 } 5679 } 5680 } 5681 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,perms,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets,PETSC_TRUE);CHKERRQ(ierr); 5682 if (newNumPoints) { 5683 if (valCopy) { 5684 ierr = DMRestoreWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 5685 } 5686 for (f = 0; f < PetscMax(1,numFields); f++) { 5687 if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5688 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5689 } 5690 for (f = 0; f < PetscMax(1,numFields); f++) { 5691 if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,newNumPoints,newPoints,&perms[f],&flips[f]);CHKERRQ(ierr);} 5692 else {ierr = PetscSectionGetPointSyms(section,newNumPoints,newPoints,&perms[f],&flips[f]);CHKERRQ(ierr);} 5693 } 5694 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5695 numPoints = newNumPoints; 5696 numIndices = newNumIndices; 5697 points = newPoints; 5698 values = newValues; 5699 } 5700 ierr = DMGetWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr); 5701 if (numFields) { 5702 for (p = 0; p < numPoints; p++) { 5703 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5704 DMPlexGetIndicesPointFields_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, perms, p, indices); 5705 } 5706 } else { 5707 for (p = 0, off = 0; p < numPoints; p++) { 5708 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 5709 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5710 DMPlexGetIndicesPoint_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, indices); 5711 } 5712 } 5713 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 5714 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 5715 if (mesh->printFEM > 1) { 5716 PetscInt i; 5717 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 5718 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 5719 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5720 } 5721 if (ierr) { 5722 PetscMPIInt rank; 5723 PetscErrorCode ierr2; 5724 5725 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5726 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5727 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 5728 ierr2 = DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr2); 5729 CHKERRQ(ierr); 5730 } 5731 for (f = 0; f < PetscMax(1,numFields); f++) { 5732 if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5733 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5734 } 5735 if (newNumPoints) { 5736 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 5737 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5738 } 5739 else { 5740 if (valCopy) { 5741 ierr = DMRestoreWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 5742 } 5743 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5744 } 5745 ierr = DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr); 5746 PetscFunctionReturn(0); 5747 } 5748 5749 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5750 { 5751 DM_Plex *mesh = (DM_Plex*) dmf->data; 5752 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5753 PetscInt *cpoints = NULL; 5754 PetscInt *findices, *cindices; 5755 PetscInt foffsets[32], coffsets[32]; 5756 CellRefiner cellRefiner; 5757 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5758 PetscErrorCode ierr; 5759 5760 PetscFunctionBegin; 5761 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5762 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5763 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 5764 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5765 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 5766 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5767 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5768 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5769 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5770 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5771 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 5772 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5773 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5774 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5775 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5776 /* Column indices */ 5777 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5778 maxFPoints = numCPoints; 5779 /* Compress out points not in the section */ 5780 /* TODO: Squeeze out points with 0 dof as well */ 5781 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5782 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5783 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5784 cpoints[q*2] = cpoints[p]; 5785 cpoints[q*2+1] = cpoints[p+1]; 5786 ++q; 5787 } 5788 } 5789 numCPoints = q; 5790 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5791 PetscInt fdof; 5792 5793 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5794 if (!dof) continue; 5795 for (f = 0; f < numFields; ++f) { 5796 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5797 coffsets[f+1] += fdof; 5798 } 5799 numCIndices += dof; 5800 } 5801 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5802 /* Row indices */ 5803 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5804 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5805 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 5806 for (r = 0, q = 0; r < numSubcells; ++r) { 5807 /* TODO Map from coarse to fine cells */ 5808 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5809 /* Compress out points not in the section */ 5810 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5811 for (p = 0; p < numFPoints*2; p += 2) { 5812 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5813 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5814 if (!dof) continue; 5815 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5816 if (s < q) continue; 5817 ftotpoints[q*2] = fpoints[p]; 5818 ftotpoints[q*2+1] = fpoints[p+1]; 5819 ++q; 5820 } 5821 } 5822 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5823 } 5824 numFPoints = q; 5825 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5826 PetscInt fdof; 5827 5828 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5829 if (!dof) continue; 5830 for (f = 0; f < numFields; ++f) { 5831 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5832 foffsets[f+1] += fdof; 5833 } 5834 numFIndices += dof; 5835 } 5836 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5837 5838 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 5839 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 5840 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 5841 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 5842 if (numFields) { 5843 const PetscInt **permsF[32] = {NULL}; 5844 const PetscInt **permsC[32] = {NULL}; 5845 5846 for (f = 0; f < numFields; f++) { 5847 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 5848 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 5849 } 5850 for (p = 0; p < numFPoints; p++) { 5851 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 5852 DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, findices); 5853 } 5854 for (p = 0; p < numCPoints; p++) { 5855 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 5856 DMPlexGetIndicesPointFields_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cindices); 5857 } 5858 for (f = 0; f < numFields; f++) { 5859 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 5860 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 5861 } 5862 } else { 5863 const PetscInt **permsF = NULL; 5864 const PetscInt **permsC = NULL; 5865 5866 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 5867 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 5868 for (p = 0, off = 0; p < numFPoints; p++) { 5869 const PetscInt *perm = permsF ? permsF[p] : NULL; 5870 5871 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 5872 ierr = DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, findices);CHKERRQ(ierr); 5873 } 5874 for (p = 0, off = 0; p < numCPoints; p++) { 5875 const PetscInt *perm = permsC ? permsC[p] : NULL; 5876 5877 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 5878 ierr = DMPlexGetIndicesPoint_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cindices);CHKERRQ(ierr); 5879 } 5880 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 5881 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 5882 } 5883 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 5884 /* TODO: flips */ 5885 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 5886 if (ierr) { 5887 PetscMPIInt rank; 5888 PetscErrorCode ierr2; 5889 5890 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5891 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5892 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 5893 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 5894 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 5895 CHKERRQ(ierr); 5896 } 5897 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 5898 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5899 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 5900 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 5901 PetscFunctionReturn(0); 5902 } 5903 5904 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 5905 { 5906 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5907 PetscInt *cpoints = NULL; 5908 PetscInt foffsets[32], coffsets[32]; 5909 CellRefiner cellRefiner; 5910 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5911 PetscErrorCode ierr; 5912 5913 PetscFunctionBegin; 5914 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5915 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5916 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 5917 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5918 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 5919 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5920 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5921 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5922 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5923 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5924 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5925 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5926 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5927 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5928 /* Column indices */ 5929 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5930 maxFPoints = numCPoints; 5931 /* Compress out points not in the section */ 5932 /* TODO: Squeeze out points with 0 dof as well */ 5933 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5934 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5935 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5936 cpoints[q*2] = cpoints[p]; 5937 cpoints[q*2+1] = cpoints[p+1]; 5938 ++q; 5939 } 5940 } 5941 numCPoints = q; 5942 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5943 PetscInt fdof; 5944 5945 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5946 if (!dof) continue; 5947 for (f = 0; f < numFields; ++f) { 5948 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5949 coffsets[f+1] += fdof; 5950 } 5951 numCIndices += dof; 5952 } 5953 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5954 /* Row indices */ 5955 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5956 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5957 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 5958 for (r = 0, q = 0; r < numSubcells; ++r) { 5959 /* TODO Map from coarse to fine cells */ 5960 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5961 /* Compress out points not in the section */ 5962 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5963 for (p = 0; p < numFPoints*2; p += 2) { 5964 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5965 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5966 if (!dof) continue; 5967 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5968 if (s < q) continue; 5969 ftotpoints[q*2] = fpoints[p]; 5970 ftotpoints[q*2+1] = fpoints[p+1]; 5971 ++q; 5972 } 5973 } 5974 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5975 } 5976 numFPoints = q; 5977 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5978 PetscInt fdof; 5979 5980 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5981 if (!dof) continue; 5982 for (f = 0; f < numFields; ++f) { 5983 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5984 foffsets[f+1] += fdof; 5985 } 5986 numFIndices += dof; 5987 } 5988 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5989 5990 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 5991 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 5992 if (numFields) { 5993 const PetscInt **permsF[32] = {NULL}; 5994 const PetscInt **permsC[32] = {NULL}; 5995 5996 for (f = 0; f < numFields; f++) { 5997 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 5998 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 5999 } 6000 for (p = 0; p < numFPoints; p++) { 6001 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6002 DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, findices); 6003 } 6004 for (p = 0; p < numCPoints; p++) { 6005 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 6006 DMPlexGetIndicesPointFields_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cindices); 6007 } 6008 for (f = 0; f < numFields; f++) { 6009 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 6010 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6011 } 6012 } else { 6013 const PetscInt **permsF = NULL; 6014 const PetscInt **permsC = NULL; 6015 6016 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 6017 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6018 for (p = 0, off = 0; p < numFPoints; p++) { 6019 const PetscInt *perm = permsF ? permsF[p] : NULL; 6020 6021 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6022 DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, findices); 6023 } 6024 for (p = 0, off = 0; p < numCPoints; p++) { 6025 const PetscInt *perm = permsC ? permsC[p] : NULL; 6026 6027 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 6028 DMPlexGetIndicesPoint_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cindices); 6029 } 6030 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 6031 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6032 } 6033 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6034 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 6035 PetscFunctionReturn(0); 6036 } 6037 6038 /*@ 6039 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 6040 6041 Input Parameter: 6042 . dm - The DMPlex object 6043 6044 Output Parameters: 6045 + cMax - The first hybrid cell 6046 . fMax - The first hybrid face 6047 . eMax - The first hybrid edge 6048 - vMax - The first hybrid vertex 6049 6050 Level: developer 6051 6052 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 6053 @*/ 6054 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 6055 { 6056 DM_Plex *mesh = (DM_Plex*) dm->data; 6057 PetscInt dim; 6058 PetscErrorCode ierr; 6059 6060 PetscFunctionBegin; 6061 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6062 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6063 if (cMax) *cMax = mesh->hybridPointMax[dim]; 6064 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 6065 if (eMax) *eMax = mesh->hybridPointMax[1]; 6066 if (vMax) *vMax = mesh->hybridPointMax[0]; 6067 PetscFunctionReturn(0); 6068 } 6069 6070 static PetscErrorCode DMPlexCreateDimStratum(DM dm, DMLabel depthLabel, DMLabel dimLabel, PetscInt d, PetscInt dMax) 6071 { 6072 IS is, his; 6073 PetscInt first, stride; 6074 PetscBool isStride; 6075 PetscErrorCode ierr; 6076 6077 PetscFunctionBegin; 6078 ierr = DMLabelGetStratumIS(depthLabel, d, &is);CHKERRQ(ierr); 6079 ierr = PetscObjectTypeCompare((PetscObject) is, ISSTRIDE, &isStride);CHKERRQ(ierr); 6080 if (isStride) { 6081 ierr = ISStrideGetInfo(is, &first, &stride);CHKERRQ(ierr); 6082 } 6083 if (!isStride || stride != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM is not stratified: depth %D IS is not contiguous", d); 6084 ierr = ISCreateStride(PETSC_COMM_SELF, (dMax - first), first, 1, &his);CHKERRQ(ierr); 6085 ierr = DMLabelSetStratumIS(dimLabel, d, his);CHKERRQ(ierr); 6086 ierr = ISDestroy(&his);CHKERRQ(ierr); 6087 ierr = ISDestroy(&is);CHKERRQ(ierr); 6088 PetscFunctionReturn(0); 6089 } 6090 6091 /*@ 6092 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 6093 6094 Input Parameters: 6095 . dm - The DMPlex object 6096 . cMax - The first hybrid cell 6097 . fMax - The first hybrid face 6098 . eMax - The first hybrid edge 6099 - vMax - The first hybrid vertex 6100 6101 Level: developer 6102 6103 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 6104 @*/ 6105 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 6106 { 6107 DM_Plex *mesh = (DM_Plex*) dm->data; 6108 PetscInt dim; 6109 DMLabel depthLabel; 6110 DMLabel dimLabel; 6111 PetscErrorCode ierr; 6112 6113 PetscFunctionBegin; 6114 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6115 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6116 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 6117 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 6118 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 6119 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 6120 ierr = DMGetLabel(dm, "dim", &dimLabel);CHKERRQ(ierr); 6121 if (!dimLabel) { 6122 ierr = DMCreateLabel(dm, "dim");CHKERRQ(ierr); 6123 ierr = DMGetLabel(dm, "dim", &dimLabel);CHKERRQ(ierr); 6124 } 6125 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 6126 if (cMax >= 0) {ierr = DMPlexCreateDimStratum(dm, depthLabel, dimLabel, dim, cMax);CHKERRQ(ierr);} 6127 if (fMax >= 0) {ierr = DMPlexCreateDimStratum(dm, depthLabel, dimLabel, dim - 1, fMax);CHKERRQ(ierr);} 6128 if (eMax >= 0) {ierr = DMPlexCreateDimStratum(dm, depthLabel, dimLabel, 1, eMax);CHKERRQ(ierr);} 6129 if (vMax >= 0) {ierr = DMPlexCreateDimStratum(dm, depthLabel, dimLabel, 0, vMax);CHKERRQ(ierr);} 6130 PetscFunctionReturn(0); 6131 } 6132 6133 /*@C 6134 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 6135 6136 Input Parameter: 6137 . dm - The DMPlex object 6138 6139 Output Parameter: 6140 . cellHeight - The height of a cell 6141 6142 Level: developer 6143 6144 .seealso DMPlexSetVTKCellHeight() 6145 @*/ 6146 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 6147 { 6148 DM_Plex *mesh = (DM_Plex*) dm->data; 6149 6150 PetscFunctionBegin; 6151 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6152 PetscValidPointer(cellHeight, 2); 6153 *cellHeight = mesh->vtkCellHeight; 6154 PetscFunctionReturn(0); 6155 } 6156 6157 /*@C 6158 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 6159 6160 Input Parameters: 6161 + dm - The DMPlex object 6162 - cellHeight - The height of a cell 6163 6164 Level: developer 6165 6166 .seealso DMPlexGetVTKCellHeight() 6167 @*/ 6168 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 6169 { 6170 DM_Plex *mesh = (DM_Plex*) dm->data; 6171 6172 PetscFunctionBegin; 6173 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6174 mesh->vtkCellHeight = cellHeight; 6175 PetscFunctionReturn(0); 6176 } 6177 6178 /* We can easily have a form that takes an IS instead */ 6179 static PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 6180 { 6181 PetscSection section, globalSection; 6182 PetscInt *numbers, p; 6183 PetscErrorCode ierr; 6184 6185 PetscFunctionBegin; 6186 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 6187 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 6188 for (p = pStart; p < pEnd; ++p) { 6189 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 6190 } 6191 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 6192 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 6193 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 6194 for (p = pStart; p < pEnd; ++p) { 6195 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 6196 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 6197 else numbers[p-pStart] += shift; 6198 } 6199 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 6200 if (globalSize) { 6201 PetscLayout layout; 6202 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 6203 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 6204 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 6205 } 6206 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6207 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 6208 PetscFunctionReturn(0); 6209 } 6210 6211 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 6212 { 6213 PetscInt cellHeight, cStart, cEnd, cMax; 6214 PetscErrorCode ierr; 6215 6216 PetscFunctionBegin; 6217 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 6218 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 6219 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 6220 if (cMax >= 0 && !includeHybrid) cEnd = PetscMin(cEnd, cMax); 6221 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 6222 PetscFunctionReturn(0); 6223 } 6224 6225 /*@C 6226 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 6227 6228 Input Parameter: 6229 . dm - The DMPlex object 6230 6231 Output Parameter: 6232 . globalCellNumbers - Global cell numbers for all cells on this process 6233 6234 Level: developer 6235 6236 .seealso DMPlexGetVertexNumbering() 6237 @*/ 6238 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 6239 { 6240 DM_Plex *mesh = (DM_Plex*) dm->data; 6241 PetscErrorCode ierr; 6242 6243 PetscFunctionBegin; 6244 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6245 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 6246 *globalCellNumbers = mesh->globalCellNumbers; 6247 PetscFunctionReturn(0); 6248 } 6249 6250 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 6251 { 6252 PetscInt vStart, vEnd, vMax; 6253 PetscErrorCode ierr; 6254 6255 PetscFunctionBegin; 6256 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6257 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6258 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 6259 if (vMax >= 0 && !includeHybrid) vEnd = PetscMin(vEnd, vMax); 6260 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 6261 PetscFunctionReturn(0); 6262 } 6263 6264 /*@C 6265 DMPlexGetVertexNumbering - Get a global certex numbering for all vertices on this process 6266 6267 Input Parameter: 6268 . dm - The DMPlex object 6269 6270 Output Parameter: 6271 . globalVertexNumbers - Global vertex numbers for all vertices on this process 6272 6273 Level: developer 6274 6275 .seealso DMPlexGetCellNumbering() 6276 @*/ 6277 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 6278 { 6279 DM_Plex *mesh = (DM_Plex*) dm->data; 6280 PetscErrorCode ierr; 6281 6282 PetscFunctionBegin; 6283 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6284 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 6285 *globalVertexNumbers = mesh->globalVertexNumbers; 6286 PetscFunctionReturn(0); 6287 } 6288 6289 /*@C 6290 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 6291 6292 Input Parameter: 6293 . dm - The DMPlex object 6294 6295 Output Parameter: 6296 . globalPointNumbers - Global numbers for all points on this process 6297 6298 Level: developer 6299 6300 .seealso DMPlexGetCellNumbering() 6301 @*/ 6302 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 6303 { 6304 IS nums[4]; 6305 PetscInt depths[4]; 6306 PetscInt depth, d, shift = 0; 6307 PetscErrorCode ierr; 6308 6309 PetscFunctionBegin; 6310 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6311 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6312 /* For unstratified meshes use dim instead of depth */ 6313 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 6314 depths[0] = depth; depths[1] = 0; 6315 for (d = 2; d <= depth; ++d) depths[d] = depth-d+1; 6316 for (d = 0; d <= depth; ++d) { 6317 PetscInt pStart, pEnd, gsize; 6318 6319 ierr = DMPlexGetDepthStratum(dm, depths[d], &pStart, &pEnd);CHKERRQ(ierr); 6320 ierr = DMPlexCreateNumbering_Private(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 6321 shift += gsize; 6322 } 6323 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 6324 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 6325 PetscFunctionReturn(0); 6326 } 6327 6328 6329 /*@ 6330 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 6331 6332 Input Parameter: 6333 . dm - The DMPlex object 6334 6335 Output Parameter: 6336 . ranks - The rank field 6337 6338 Options Database Keys: 6339 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 6340 6341 Level: intermediate 6342 6343 .seealso: DMView() 6344 @*/ 6345 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 6346 { 6347 DM rdm; 6348 PetscDS prob; 6349 PetscFE fe; 6350 PetscScalar *r; 6351 PetscMPIInt rank; 6352 PetscInt dim, cStart, cEnd, c; 6353 PetscErrorCode ierr; 6354 6355 PetscFunctionBeginUser; 6356 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 6357 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 6358 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 6359 ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, NULL, -1, &fe);CHKERRQ(ierr); 6360 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 6361 ierr = DMGetDS(rdm, &prob);CHKERRQ(ierr); 6362 ierr = PetscDSSetDiscretization(prob, 0, (PetscObject) fe);CHKERRQ(ierr); 6363 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 6364 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6365 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 6366 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 6367 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 6368 for (c = cStart; c < cEnd; ++c) { 6369 PetscScalar *lr; 6370 6371 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 6372 *lr = rank; 6373 } 6374 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 6375 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 6376 PetscFunctionReturn(0); 6377 } 6378 6379 /*@ 6380 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 6381 6382 Input Parameter: 6383 . dm - The DMPlex object 6384 6385 Note: This is a useful diagnostic when creating meshes programmatically. 6386 6387 Level: developer 6388 6389 .seealso: DMCreate(), DMCheckSkeleton(), DMCheckFaces() 6390 @*/ 6391 PetscErrorCode DMPlexCheckSymmetry(DM dm) 6392 { 6393 PetscSection coneSection, supportSection; 6394 const PetscInt *cone, *support; 6395 PetscInt coneSize, c, supportSize, s; 6396 PetscInt pStart, pEnd, p, csize, ssize; 6397 PetscErrorCode ierr; 6398 6399 PetscFunctionBegin; 6400 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6401 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 6402 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 6403 /* Check that point p is found in the support of its cone points, and vice versa */ 6404 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6405 for (p = pStart; p < pEnd; ++p) { 6406 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 6407 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 6408 for (c = 0; c < coneSize; ++c) { 6409 PetscBool dup = PETSC_FALSE; 6410 PetscInt d; 6411 for (d = c-1; d >= 0; --d) { 6412 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 6413 } 6414 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 6415 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 6416 for (s = 0; s < supportSize; ++s) { 6417 if (support[s] == p) break; 6418 } 6419 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 6420 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 6421 for (s = 0; s < coneSize; ++s) { 6422 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 6423 } 6424 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6425 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 6426 for (s = 0; s < supportSize; ++s) { 6427 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 6428 } 6429 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6430 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 6431 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 6432 } 6433 } 6434 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 6435 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 6436 for (s = 0; s < supportSize; ++s) { 6437 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6438 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6439 for (c = 0; c < coneSize; ++c) { 6440 if (cone[c] == p) break; 6441 } 6442 if (c >= coneSize) { 6443 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 6444 for (c = 0; c < supportSize; ++c) { 6445 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 6446 } 6447 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6448 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 6449 for (c = 0; c < coneSize; ++c) { 6450 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 6451 } 6452 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6453 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 6454 } 6455 } 6456 } 6457 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 6458 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 6459 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 6460 PetscFunctionReturn(0); 6461 } 6462 6463 /*@ 6464 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 6465 6466 Input Parameters: 6467 + dm - The DMPlex object 6468 . isSimplex - Are the cells simplices or tensor products 6469 - cellHeight - Normally 0 6470 6471 Note: This is a useful diagnostic when creating meshes programmatically. 6472 6473 Level: developer 6474 6475 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckFaces() 6476 @*/ 6477 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight) 6478 { 6479 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 6480 PetscErrorCode ierr; 6481 6482 PetscFunctionBegin; 6483 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6484 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6485 switch (dim) { 6486 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 6487 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 6488 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 6489 default: 6490 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %D", dim); 6491 } 6492 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6493 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 6494 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 6495 cMax = cMax >= 0 ? cMax : cEnd; 6496 for (c = cStart; c < cMax; ++c) { 6497 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 6498 6499 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6500 for (cl = 0; cl < closureSize*2; cl += 2) { 6501 const PetscInt p = closure[cl]; 6502 if ((p >= vStart) && (p < vEnd)) ++coneSize; 6503 } 6504 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6505 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has %D vertices != %D", c, coneSize, numCorners); 6506 } 6507 for (c = cMax; c < cEnd; ++c) { 6508 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 6509 6510 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6511 for (cl = 0; cl < closureSize*2; cl += 2) { 6512 const PetscInt p = closure[cl]; 6513 if ((p >= vStart) && (p < vEnd)) ++coneSize; 6514 } 6515 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6516 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %D has %D vertices > %D", c, coneSize, numHybridCorners); 6517 } 6518 PetscFunctionReturn(0); 6519 } 6520 6521 /*@ 6522 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 6523 6524 Input Parameters: 6525 + dm - The DMPlex object 6526 . isSimplex - Are the cells simplices or tensor products 6527 - cellHeight - Normally 0 6528 6529 Note: This is a useful diagnostic when creating meshes programmatically. 6530 6531 Level: developer 6532 6533 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton() 6534 @*/ 6535 PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight) 6536 { 6537 PetscInt pMax[4]; 6538 PetscInt dim, vStart, vEnd, cStart, cEnd, c, h; 6539 PetscErrorCode ierr; 6540 6541 PetscFunctionBegin; 6542 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6543 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6544 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6545 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 6546 for (h = cellHeight; h < dim; ++h) { 6547 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 6548 for (c = cStart; c < cEnd; ++c) { 6549 const PetscInt *cone, *ornt, *faces; 6550 PetscInt numFaces, faceSize, coneSize,f; 6551 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 6552 6553 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 6554 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 6555 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6556 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6557 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6558 for (cl = 0; cl < closureSize*2; cl += 2) { 6559 const PetscInt p = closure[cl]; 6560 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 6561 } 6562 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 6563 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has %D faces but should have %D", c, coneSize, numFaces); 6564 for (f = 0; f < numFaces; ++f) { 6565 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 6566 6567 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 6568 for (cl = 0; cl < fclosureSize*2; cl += 2) { 6569 const PetscInt p = fclosure[cl]; 6570 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 6571 } 6572 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); 6573 for (v = 0; v < fnumCorners; ++v) { 6574 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]); 6575 } 6576 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 6577 } 6578 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 6579 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6580 } 6581 } 6582 PetscFunctionReturn(0); 6583 } 6584 6585 /* Pointwise interpolation 6586 Just code FEM for now 6587 u^f = I u^c 6588 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 6589 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 6590 I_{ij} = psi^f_i phi^c_j 6591 */ 6592 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 6593 { 6594 PetscSection gsc, gsf; 6595 PetscInt m, n; 6596 void *ctx; 6597 DM cdm; 6598 PetscBool regular; 6599 PetscErrorCode ierr; 6600 6601 PetscFunctionBegin; 6602 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 6603 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 6604 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 6605 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 6606 6607 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 6608 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6609 ierr = MatSetType(*interpolation, dmCoarse->mattype);CHKERRQ(ierr); 6610 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 6611 6612 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 6613 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 6614 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 6615 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 6616 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 6617 /* Use naive scaling */ 6618 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 6619 PetscFunctionReturn(0); 6620 } 6621 6622 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 6623 { 6624 PetscErrorCode ierr; 6625 VecScatter ctx; 6626 6627 PetscFunctionBegin; 6628 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 6629 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 6630 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 6631 PetscFunctionReturn(0); 6632 } 6633 6634 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 6635 { 6636 PetscSection gsc, gsf; 6637 PetscInt m, n; 6638 void *ctx; 6639 DM cdm; 6640 PetscBool regular; 6641 PetscErrorCode ierr; 6642 6643 PetscFunctionBegin; 6644 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 6645 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 6646 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 6647 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 6648 6649 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 6650 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6651 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 6652 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 6653 6654 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 6655 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 6656 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 6657 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 6658 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 6659 PetscFunctionReturn(0); 6660 } 6661 6662 PetscErrorCode DMCreateDefaultSection_Plex(DM dm) 6663 { 6664 PetscSection section; 6665 IS *bcPoints, *bcComps; 6666 PetscBool *isFE; 6667 PetscInt *bcFields, *numComp, *numDof; 6668 PetscInt depth, dim, numBd, numBC = 0, numFields, bd, bc = 0, f; 6669 PetscInt cStart, cEnd, cEndInterior; 6670 PetscErrorCode ierr; 6671 6672 PetscFunctionBegin; 6673 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 6674 /* FE and FV boundary conditions are handled slightly differently */ 6675 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 6676 for (f = 0; f < numFields; ++f) { 6677 PetscObject obj; 6678 PetscClassId id; 6679 6680 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 6681 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 6682 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 6683 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 6684 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %D", f); 6685 } 6686 /* Allocate boundary point storage for FEM boundaries */ 6687 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6688 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6689 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6690 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 6691 ierr = PetscDSGetNumBoundary(dm->prob, &numBd);CHKERRQ(ierr); 6692 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)"); 6693 for (bd = 0; bd < numBd; ++bd) { 6694 PetscInt field; 6695 DMBoundaryConditionType type; 6696 const char *labelName; 6697 DMLabel label; 6698 6699 ierr = PetscDSGetBoundary(dm->prob, bd, &type, NULL, &labelName, &field, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 6700 ierr = DMGetLabel(dm,labelName,&label);CHKERRQ(ierr); 6701 if (label && isFE[field] && (type & DM_BC_ESSENTIAL)) ++numBC; 6702 } 6703 /* Add ghost cell boundaries for FVM */ 6704 for (f = 0; f < numFields; ++f) if (!isFE[f] && cEndInterior >= 0) ++numBC; 6705 ierr = PetscCalloc3(numBC,&bcFields,numBC,&bcPoints,numBC,&bcComps);CHKERRQ(ierr); 6706 /* Constrain ghost cells for FV */ 6707 for (f = 0; f < numFields; ++f) { 6708 PetscInt *newidx, c; 6709 6710 if (isFE[f] || cEndInterior < 0) continue; 6711 ierr = PetscMalloc1(cEnd-cEndInterior,&newidx);CHKERRQ(ierr); 6712 for (c = cEndInterior; c < cEnd; ++c) newidx[c-cEndInterior] = c; 6713 bcFields[bc] = f; 6714 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), cEnd-cEndInterior, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 6715 } 6716 /* Handle FEM Dirichlet boundaries */ 6717 for (bd = 0; bd < numBd; ++bd) { 6718 const char *bdLabel; 6719 DMLabel label; 6720 const PetscInt *comps; 6721 const PetscInt *values; 6722 PetscInt bd2, field, numComps, numValues; 6723 DMBoundaryConditionType type; 6724 PetscBool duplicate = PETSC_FALSE; 6725 6726 ierr = PetscDSGetBoundary(dm->prob, bd, &type, NULL, &bdLabel, &field, &numComps, &comps, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 6727 ierr = DMGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 6728 if (!isFE[field] || !label) continue; 6729 /* Only want to modify label once */ 6730 for (bd2 = 0; bd2 < bd; ++bd2) { 6731 const char *bdname; 6732 ierr = PetscDSGetBoundary(dm->prob, bd2, NULL, NULL, &bdname, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 6733 ierr = PetscStrcmp(bdname, bdLabel, &duplicate);CHKERRQ(ierr); 6734 if (duplicate) break; 6735 } 6736 if (!duplicate && (isFE[field])) { 6737 /* don't complete cells, which are just present to give orientation to the boundary */ 6738 ierr = DMPlexLabelComplete(dm, label);CHKERRQ(ierr); 6739 } 6740 /* Filter out cells, if you actually want to constrain cells you need to do things by hand right now */ 6741 if (type & DM_BC_ESSENTIAL) { 6742 PetscInt *newidx; 6743 PetscInt n, newn = 0, p, v; 6744 6745 bcFields[bc] = field; 6746 if (numComps) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), numComps, comps, PETSC_COPY_VALUES, &bcComps[bc]);CHKERRQ(ierr);} 6747 for (v = 0; v < numValues; ++v) { 6748 IS tmp; 6749 const PetscInt *idx; 6750 6751 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 6752 if (!tmp) continue; 6753 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 6754 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 6755 if (isFE[field]) { 6756 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) ++newn; 6757 } else { 6758 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) ++newn; 6759 } 6760 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 6761 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 6762 } 6763 ierr = PetscMalloc1(newn,&newidx);CHKERRQ(ierr); 6764 newn = 0; 6765 for (v = 0; v < numValues; ++v) { 6766 IS tmp; 6767 const PetscInt *idx; 6768 6769 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 6770 if (!tmp) continue; 6771 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 6772 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 6773 if (isFE[field]) { 6774 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) newidx[newn++] = idx[p]; 6775 } else { 6776 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) newidx[newn++] = idx[p]; 6777 } 6778 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 6779 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 6780 } 6781 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), newn, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 6782 } 6783 } 6784 /* Handle discretization */ 6785 ierr = PetscCalloc2(numFields,&numComp,numFields*(dim+1),&numDof);CHKERRQ(ierr); 6786 for (f = 0; f < numFields; ++f) { 6787 PetscObject obj; 6788 6789 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 6790 if (isFE[f]) { 6791 PetscFE fe = (PetscFE) obj; 6792 const PetscInt *numFieldDof; 6793 PetscInt d; 6794 6795 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 6796 ierr = PetscFEGetNumDof(fe, &numFieldDof);CHKERRQ(ierr); 6797 for (d = 0; d < dim+1; ++d) numDof[f*(dim+1)+d] = numFieldDof[d]; 6798 } else { 6799 PetscFV fv = (PetscFV) obj; 6800 6801 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 6802 numDof[f*(dim+1)+dim] = numComp[f]; 6803 } 6804 } 6805 for (f = 0; f < numFields; ++f) { 6806 PetscInt d; 6807 for (d = 1; d < dim; ++d) { 6808 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."); 6809 } 6810 } 6811 ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcComps, bcPoints, NULL, §ion);CHKERRQ(ierr); 6812 for (f = 0; f < numFields; ++f) { 6813 PetscFE fe; 6814 const char *name; 6815 6816 ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 6817 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 6818 ierr = PetscSectionSetFieldName(section, f, name);CHKERRQ(ierr); 6819 } 6820 ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); 6821 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6822 for (bc = 0; bc < numBC; ++bc) {ierr = ISDestroy(&bcPoints[bc]);CHKERRQ(ierr);ierr = ISDestroy(&bcComps[bc]);CHKERRQ(ierr);} 6823 ierr = PetscFree3(bcFields,bcPoints,bcComps);CHKERRQ(ierr); 6824 ierr = PetscFree2(numComp,numDof);CHKERRQ(ierr); 6825 ierr = PetscFree(isFE);CHKERRQ(ierr); 6826 PetscFunctionReturn(0); 6827 } 6828 6829 /*@ 6830 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 6831 6832 Input Parameter: 6833 . dm - The DMPlex object 6834 6835 Output Parameter: 6836 . regular - The flag 6837 6838 Level: intermediate 6839 6840 .seealso: DMPlexSetRegularRefinement() 6841 @*/ 6842 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 6843 { 6844 PetscFunctionBegin; 6845 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6846 PetscValidPointer(regular, 2); 6847 *regular = ((DM_Plex *) dm->data)->regularRefinement; 6848 PetscFunctionReturn(0); 6849 } 6850 6851 /*@ 6852 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 6853 6854 Input Parameters: 6855 + dm - The DMPlex object 6856 - regular - The flag 6857 6858 Level: intermediate 6859 6860 .seealso: DMPlexGetRegularRefinement() 6861 @*/ 6862 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 6863 { 6864 PetscFunctionBegin; 6865 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6866 ((DM_Plex *) dm->data)->regularRefinement = regular; 6867 PetscFunctionReturn(0); 6868 } 6869 6870 /* anchors */ 6871 /*@ 6872 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 6873 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 6874 6875 not collective 6876 6877 Input Parameters: 6878 . dm - The DMPlex object 6879 6880 Output Parameters: 6881 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 6882 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 6883 6884 6885 Level: intermediate 6886 6887 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 6888 @*/ 6889 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 6890 { 6891 DM_Plex *plex = (DM_Plex *)dm->data; 6892 PetscErrorCode ierr; 6893 6894 PetscFunctionBegin; 6895 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6896 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 6897 if (anchorSection) *anchorSection = plex->anchorSection; 6898 if (anchorIS) *anchorIS = plex->anchorIS; 6899 PetscFunctionReturn(0); 6900 } 6901 6902 /*@ 6903 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 6904 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 6905 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 6906 6907 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 6908 DMGetConstraints() and filling in the entries in the constraint matrix. 6909 6910 collective on dm 6911 6912 Input Parameters: 6913 + dm - The DMPlex object 6914 . 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). 6915 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 6916 6917 The reference counts of anchorSection and anchorIS are incremented. 6918 6919 Level: intermediate 6920 6921 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 6922 @*/ 6923 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 6924 { 6925 DM_Plex *plex = (DM_Plex *)dm->data; 6926 PetscMPIInt result; 6927 PetscErrorCode ierr; 6928 6929 PetscFunctionBegin; 6930 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6931 if (anchorSection) { 6932 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 6933 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 6934 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 6935 } 6936 if (anchorIS) { 6937 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 6938 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 6939 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 6940 } 6941 6942 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 6943 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 6944 plex->anchorSection = anchorSection; 6945 6946 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 6947 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 6948 plex->anchorIS = anchorIS; 6949 6950 #if defined(PETSC_USE_DEBUG) 6951 if (anchorIS && anchorSection) { 6952 PetscInt size, a, pStart, pEnd; 6953 const PetscInt *anchors; 6954 6955 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 6956 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 6957 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 6958 for (a = 0; a < size; a++) { 6959 PetscInt p; 6960 6961 p = anchors[a]; 6962 if (p >= pStart && p < pEnd) { 6963 PetscInt dof; 6964 6965 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 6966 if (dof) { 6967 PetscErrorCode ierr2; 6968 6969 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 6970 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 6971 } 6972 } 6973 } 6974 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 6975 } 6976 #endif 6977 /* reset the generic constraints */ 6978 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 6979 PetscFunctionReturn(0); 6980 } 6981 6982 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 6983 { 6984 PetscSection anchorSection; 6985 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 6986 PetscErrorCode ierr; 6987 6988 PetscFunctionBegin; 6989 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6990 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 6991 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 6992 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 6993 if (numFields) { 6994 PetscInt f; 6995 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 6996 6997 for (f = 0; f < numFields; f++) { 6998 PetscInt numComp; 6999 7000 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 7001 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 7002 } 7003 } 7004 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 7005 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 7006 pStart = PetscMax(pStart,sStart); 7007 pEnd = PetscMin(pEnd,sEnd); 7008 pEnd = PetscMax(pStart,pEnd); 7009 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 7010 for (p = pStart; p < pEnd; p++) { 7011 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 7012 if (dof) { 7013 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 7014 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 7015 for (f = 0; f < numFields; f++) { 7016 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 7017 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 7018 } 7019 } 7020 } 7021 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 7022 PetscFunctionReturn(0); 7023 } 7024 7025 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 7026 { 7027 PetscSection aSec; 7028 PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 7029 const PetscInt *anchors; 7030 PetscInt numFields, f; 7031 IS aIS; 7032 PetscErrorCode ierr; 7033 7034 PetscFunctionBegin; 7035 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7036 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 7037 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 7038 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 7039 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 7040 ierr = MatSetType(*cMat,MATSEQAIJ);CHKERRQ(ierr); 7041 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 7042 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 7043 /* cSec will be a subset of aSec and section */ 7044 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 7045 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 7046 i[0] = 0; 7047 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 7048 for (p = pStart; p < pEnd; p++) { 7049 PetscInt rDof, rOff, r; 7050 7051 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 7052 if (!rDof) continue; 7053 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 7054 if (numFields) { 7055 for (f = 0; f < numFields; f++) { 7056 annz = 0; 7057 for (r = 0; r < rDof; r++) { 7058 a = anchors[rOff + r]; 7059 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 7060 annz += aDof; 7061 } 7062 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 7063 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 7064 for (q = 0; q < dof; q++) { 7065 i[off + q + 1] = i[off + q] + annz; 7066 } 7067 } 7068 } 7069 else { 7070 annz = 0; 7071 for (q = 0; q < dof; q++) { 7072 a = anchors[off + q]; 7073 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 7074 annz += aDof; 7075 } 7076 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 7077 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 7078 for (q = 0; q < dof; q++) { 7079 i[off + q + 1] = i[off + q] + annz; 7080 } 7081 } 7082 } 7083 nnz = i[m]; 7084 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 7085 offset = 0; 7086 for (p = pStart; p < pEnd; p++) { 7087 if (numFields) { 7088 for (f = 0; f < numFields; f++) { 7089 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 7090 for (q = 0; q < dof; q++) { 7091 PetscInt rDof, rOff, r; 7092 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 7093 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 7094 for (r = 0; r < rDof; r++) { 7095 PetscInt s; 7096 7097 a = anchors[rOff + r]; 7098 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 7099 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 7100 for (s = 0; s < aDof; s++) { 7101 j[offset++] = aOff + s; 7102 } 7103 } 7104 } 7105 } 7106 } 7107 else { 7108 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 7109 for (q = 0; q < dof; q++) { 7110 PetscInt rDof, rOff, r; 7111 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 7112 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 7113 for (r = 0; r < rDof; r++) { 7114 PetscInt s; 7115 7116 a = anchors[rOff + r]; 7117 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 7118 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 7119 for (s = 0; s < aDof; s++) { 7120 j[offset++] = aOff + s; 7121 } 7122 } 7123 } 7124 } 7125 } 7126 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 7127 ierr = PetscFree(i);CHKERRQ(ierr); 7128 ierr = PetscFree(j);CHKERRQ(ierr); 7129 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7130 PetscFunctionReturn(0); 7131 } 7132 7133 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 7134 { 7135 DM_Plex *plex = (DM_Plex *)dm->data; 7136 PetscSection anchorSection, section, cSec; 7137 Mat cMat; 7138 PetscErrorCode ierr; 7139 7140 PetscFunctionBegin; 7141 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7142 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 7143 if (anchorSection) { 7144 PetscDS ds; 7145 PetscInt nf; 7146 7147 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 7148 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 7149 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 7150 ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 7151 ierr = PetscDSGetNumFields(ds,&nf);CHKERRQ(ierr); 7152 if (nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 7153 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 7154 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 7155 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 7156 } 7157 PetscFunctionReturn(0); 7158 } 7159