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