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 if (subdm) {(*subdm)->useNatural = dm->useNatural;} 2200 if (dm->useNatural && dm->sfMigration) { 2201 PetscSF sfMigrationInv,sfNatural; 2202 PetscSection section, sectionSeq; 2203 2204 (*subdm)->sfMigration = dm->sfMigration; 2205 ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr); 2206 ierr = DMGetDefaultSection((*subdm), §ion);CHKERRQ(ierr);CHKERRQ(ierr); 2207 ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 2208 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq);CHKERRQ(ierr); 2209 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 2210 2211 ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 2212 (*subdm)->sfNatural = sfNatural; 2213 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 2214 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 2215 } 2216 PetscFunctionReturn(0); 2217 } 2218 2219 PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 2220 { 2221 PetscErrorCode ierr; 2222 PetscInt i = 0; 2223 2224 PetscFunctionBegin; 2225 if (superdm) {ierr = DMClone(dms[0], superdm);CHKERRQ(ierr);} 2226 ierr = DMCreateSuperDM_Section_Private(dms, len, is, superdm);CHKERRQ(ierr); 2227 (*superdm)->useNatural = PETSC_FALSE; 2228 for (i = 0; i < len; i++){ 2229 if (dms[i]->useNatural && dms[i]->sfMigration) { 2230 PetscSF sfMigrationInv,sfNatural; 2231 PetscSection section, sectionSeq; 2232 2233 (*superdm)->sfMigration = dms[i]->sfMigration; 2234 ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr); 2235 (*superdm)->useNatural = PETSC_TRUE; 2236 ierr = DMGetDefaultSection((*superdm), §ion);CHKERRQ(ierr);CHKERRQ(ierr); 2237 ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 2238 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq);CHKERRQ(ierr); 2239 ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 2240 2241 ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 2242 (*superdm)->sfNatural = sfNatural; 2243 ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 2244 ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 2245 break; 2246 } 2247 } 2248 PetscFunctionReturn(0); 2249 } 2250 2251 /*@ 2252 DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 2253 2254 Not collective 2255 2256 Input Parameter: 2257 . mesh - The DMPlex 2258 2259 Output Parameter: 2260 2261 Note: 2262 This should be called after all calls to DMPlexSetCone() 2263 2264 Level: beginner 2265 2266 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 2267 @*/ 2268 PetscErrorCode DMPlexSymmetrize(DM dm) 2269 { 2270 DM_Plex *mesh = (DM_Plex*) dm->data; 2271 PetscInt *offsets; 2272 PetscInt supportSize; 2273 PetscInt pStart, pEnd, p; 2274 PetscErrorCode ierr; 2275 2276 PetscFunctionBegin; 2277 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2278 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 2279 /* Calculate support sizes */ 2280 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2281 for (p = pStart; p < pEnd; ++p) { 2282 PetscInt dof, off, c; 2283 2284 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2285 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2286 for (c = off; c < off+dof; ++c) { 2287 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 2288 } 2289 } 2290 for (p = pStart; p < pEnd; ++p) { 2291 PetscInt dof; 2292 2293 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 2294 2295 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 2296 } 2297 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 2298 /* Calculate supports */ 2299 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 2300 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 2301 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 2302 for (p = pStart; p < pEnd; ++p) { 2303 PetscInt dof, off, c; 2304 2305 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2306 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2307 for (c = off; c < off+dof; ++c) { 2308 const PetscInt q = mesh->cones[c]; 2309 PetscInt offS; 2310 2311 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 2312 2313 mesh->supports[offS+offsets[q]] = p; 2314 ++offsets[q]; 2315 } 2316 } 2317 ierr = PetscFree(offsets);CHKERRQ(ierr); 2318 PetscFunctionReturn(0); 2319 } 2320 2321 /*@ 2322 DMPlexStratify - The DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2323 can be illustrated by a Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2324 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2325 the DAG. 2326 2327 Collective on dm 2328 2329 Input Parameter: 2330 . mesh - The DMPlex 2331 2332 Output Parameter: 2333 2334 Notes: 2335 Concretely, DMPlexStratify() creates a new label named "depth" containing the dimension of each element: 0 for vertices, 2336 1 for edges, and so on. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 2337 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 2338 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 2339 2340 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 2341 2342 Level: beginner 2343 2344 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2345 @*/ 2346 PetscErrorCode DMPlexStratify(DM dm) 2347 { 2348 DM_Plex *mesh = (DM_Plex*) dm->data; 2349 DMLabel label; 2350 PetscInt pStart, pEnd, p; 2351 PetscInt numRoots = 0, numLeaves = 0; 2352 PetscErrorCode ierr; 2353 2354 PetscFunctionBegin; 2355 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2356 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2357 /* Calculate depth */ 2358 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2359 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 2360 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2361 /* Initialize roots and count leaves */ 2362 for (p = pStart; p < pEnd; ++p) { 2363 PetscInt coneSize, supportSize; 2364 2365 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2366 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2367 if (!coneSize && supportSize) { 2368 ++numRoots; 2369 ierr = DMLabelSetValue(label, p, 0);CHKERRQ(ierr); 2370 } else if (!supportSize && coneSize) { 2371 ++numLeaves; 2372 } else if (!supportSize && !coneSize) { 2373 /* Isolated points */ 2374 ierr = DMLabelSetValue(label, p, 0);CHKERRQ(ierr); 2375 } 2376 } 2377 if (numRoots + numLeaves == (pEnd - pStart)) { 2378 for (p = pStart; p < pEnd; ++p) { 2379 PetscInt coneSize, supportSize; 2380 2381 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2382 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2383 if (!supportSize && coneSize) { 2384 ierr = DMLabelSetValue(label, p, 1);CHKERRQ(ierr); 2385 } 2386 } 2387 } else { 2388 IS pointIS; 2389 PetscInt numPoints = 0, level = 0; 2390 2391 ierr = DMLabelGetStratumIS(label, level, &pointIS);CHKERRQ(ierr); 2392 if (pointIS) {ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);} 2393 while (numPoints) { 2394 const PetscInt *points; 2395 const PetscInt newLevel = level+1; 2396 2397 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 2398 for (p = 0; p < numPoints; ++p) { 2399 const PetscInt point = points[p]; 2400 const PetscInt *support; 2401 PetscInt supportSize, s; 2402 2403 ierr = DMPlexGetSupportSize(dm, point, &supportSize);CHKERRQ(ierr); 2404 ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr); 2405 for (s = 0; s < supportSize; ++s) { 2406 ierr = DMLabelSetValue(label, support[s], newLevel);CHKERRQ(ierr); 2407 } 2408 } 2409 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 2410 ++level; 2411 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2412 ierr = DMLabelGetStratumIS(label, level, &pointIS);CHKERRQ(ierr); 2413 if (pointIS) {ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);} 2414 else {numPoints = 0;} 2415 } 2416 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2417 } 2418 { /* just in case there is an empty process */ 2419 PetscInt numValues, maxValues = 0, v; 2420 2421 ierr = DMLabelGetNumValues(label,&numValues);CHKERRQ(ierr); 2422 for (v = 0; v < numValues; v++) { 2423 IS pointIS; 2424 2425 ierr = DMLabelGetStratumIS(label, v, &pointIS);CHKERRQ(ierr); 2426 if (pointIS) { 2427 PetscInt min, max, numPoints; 2428 PetscInt start; 2429 PetscBool contig; 2430 2431 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 2432 ierr = ISGetMinMax(pointIS, &min, &max);CHKERRQ(ierr); 2433 ierr = ISContiguousLocal(pointIS,min,max+1,&start,&contig);CHKERRQ(ierr); 2434 if (start == 0 && contig) { 2435 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2436 ierr = ISCreateStride(PETSC_COMM_SELF,numPoints,min,1,&pointIS);CHKERRQ(ierr); 2437 ierr = DMLabelSetStratumIS(label, v, pointIS);CHKERRQ(ierr); 2438 } 2439 } 2440 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2441 } 2442 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 2443 for (v = numValues; v < maxValues; v++) { 2444 DMLabelAddStratum(label,v);CHKERRQ(ierr); 2445 } 2446 } 2447 2448 ierr = DMLabelGetState(label, &mesh->depthState);CHKERRQ(ierr); 2449 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2450 PetscFunctionReturn(0); 2451 } 2452 2453 /*@C 2454 DMPlexGetJoin - Get an array for the join of the set of points 2455 2456 Not Collective 2457 2458 Input Parameters: 2459 + dm - The DMPlex object 2460 . numPoints - The number of input points for the join 2461 - points - The input points 2462 2463 Output Parameters: 2464 + numCoveredPoints - The number of points in the join 2465 - coveredPoints - The points in the join 2466 2467 Level: intermediate 2468 2469 Note: Currently, this is restricted to a single level join 2470 2471 Fortran Notes: 2472 Since it returns an array, this routine is only available in Fortran 90, and you must 2473 include petsc.h90 in your code. 2474 2475 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2476 2477 .keywords: mesh 2478 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2479 @*/ 2480 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2481 { 2482 DM_Plex *mesh = (DM_Plex*) dm->data; 2483 PetscInt *join[2]; 2484 PetscInt joinSize, i = 0; 2485 PetscInt dof, off, p, c, m; 2486 PetscErrorCode ierr; 2487 2488 PetscFunctionBegin; 2489 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2490 PetscValidPointer(points, 2); 2491 PetscValidPointer(numCoveredPoints, 3); 2492 PetscValidPointer(coveredPoints, 4); 2493 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 2494 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 2495 /* Copy in support of first point */ 2496 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2497 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2498 for (joinSize = 0; joinSize < dof; ++joinSize) { 2499 join[i][joinSize] = mesh->supports[off+joinSize]; 2500 } 2501 /* Check each successive support */ 2502 for (p = 1; p < numPoints; ++p) { 2503 PetscInt newJoinSize = 0; 2504 2505 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2506 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2507 for (c = 0; c < dof; ++c) { 2508 const PetscInt point = mesh->supports[off+c]; 2509 2510 for (m = 0; m < joinSize; ++m) { 2511 if (point == join[i][m]) { 2512 join[1-i][newJoinSize++] = point; 2513 break; 2514 } 2515 } 2516 } 2517 joinSize = newJoinSize; 2518 i = 1-i; 2519 } 2520 *numCoveredPoints = joinSize; 2521 *coveredPoints = join[i]; 2522 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 2523 PetscFunctionReturn(0); 2524 } 2525 2526 /*@C 2527 DMPlexRestoreJoin - Restore 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(), DMPlexGetFullJoin(), DMPlexGetMeet() 2550 @*/ 2551 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2552 { 2553 PetscErrorCode ierr; 2554 2555 PetscFunctionBegin; 2556 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2557 if (points) PetscValidIntPointer(points,3); 2558 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 2559 PetscValidPointer(coveredPoints, 5); 2560 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 2561 if (numCoveredPoints) *numCoveredPoints = 0; 2562 PetscFunctionReturn(0); 2563 } 2564 2565 /*@C 2566 DMPlexGetFullJoin - Get an array for the join of the set of points 2567 2568 Not Collective 2569 2570 Input Parameters: 2571 + dm - The DMPlex object 2572 . numPoints - The number of input points for the join 2573 - points - The input points 2574 2575 Output Parameters: 2576 + numCoveredPoints - The number of points in the join 2577 - coveredPoints - The points in the join 2578 2579 Fortran Notes: 2580 Since it returns an array, this routine is only available in Fortran 90, and you must 2581 include petsc.h90 in your code. 2582 2583 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2584 2585 Level: intermediate 2586 2587 .keywords: mesh 2588 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2589 @*/ 2590 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2591 { 2592 DM_Plex *mesh = (DM_Plex*) dm->data; 2593 PetscInt *offsets, **closures; 2594 PetscInt *join[2]; 2595 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2596 PetscInt p, d, c, m, ms; 2597 PetscErrorCode ierr; 2598 2599 PetscFunctionBegin; 2600 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2601 PetscValidPointer(points, 2); 2602 PetscValidPointer(numCoveredPoints, 3); 2603 PetscValidPointer(coveredPoints, 4); 2604 2605 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2606 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 2607 ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 2608 ms = mesh->maxSupportSize; 2609 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 2610 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 2611 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 2612 2613 for (p = 0; p < numPoints; ++p) { 2614 PetscInt closureSize; 2615 2616 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2617 2618 offsets[p*(depth+2)+0] = 0; 2619 for (d = 0; d < depth+1; ++d) { 2620 PetscInt pStart, pEnd, i; 2621 2622 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2623 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2624 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2625 offsets[p*(depth+2)+d+1] = i; 2626 break; 2627 } 2628 } 2629 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2630 } 2631 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); 2632 } 2633 for (d = 0; d < depth+1; ++d) { 2634 PetscInt dof; 2635 2636 /* Copy in support of first point */ 2637 dof = offsets[d+1] - offsets[d]; 2638 for (joinSize = 0; joinSize < dof; ++joinSize) { 2639 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2640 } 2641 /* Check each successive cone */ 2642 for (p = 1; p < numPoints && joinSize; ++p) { 2643 PetscInt newJoinSize = 0; 2644 2645 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2646 for (c = 0; c < dof; ++c) { 2647 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2648 2649 for (m = 0; m < joinSize; ++m) { 2650 if (point == join[i][m]) { 2651 join[1-i][newJoinSize++] = point; 2652 break; 2653 } 2654 } 2655 } 2656 joinSize = newJoinSize; 2657 i = 1-i; 2658 } 2659 if (joinSize) break; 2660 } 2661 *numCoveredPoints = joinSize; 2662 *coveredPoints = join[i]; 2663 for (p = 0; p < numPoints; ++p) { 2664 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2665 } 2666 ierr = PetscFree(closures);CHKERRQ(ierr); 2667 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 2668 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 2669 PetscFunctionReturn(0); 2670 } 2671 2672 /*@C 2673 DMPlexGetMeet - Get an array for the meet of the set of points 2674 2675 Not Collective 2676 2677 Input Parameters: 2678 + dm - The DMPlex object 2679 . numPoints - The number of input points for the meet 2680 - points - The input points 2681 2682 Output Parameters: 2683 + numCoveredPoints - The number of points in the meet 2684 - coveredPoints - The points in the meet 2685 2686 Level: intermediate 2687 2688 Note: Currently, this is restricted to a single level meet 2689 2690 Fortran Notes: 2691 Since it returns an array, this routine is only available in Fortran 90, and you must 2692 include petsc.h90 in your code. 2693 2694 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2695 2696 .keywords: mesh 2697 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2698 @*/ 2699 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2700 { 2701 DM_Plex *mesh = (DM_Plex*) dm->data; 2702 PetscInt *meet[2]; 2703 PetscInt meetSize, i = 0; 2704 PetscInt dof, off, p, c, m; 2705 PetscErrorCode ierr; 2706 2707 PetscFunctionBegin; 2708 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2709 PetscValidPointer(points, 2); 2710 PetscValidPointer(numCoveringPoints, 3); 2711 PetscValidPointer(coveringPoints, 4); 2712 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 2713 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 2714 /* Copy in cone of first point */ 2715 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2716 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2717 for (meetSize = 0; meetSize < dof; ++meetSize) { 2718 meet[i][meetSize] = mesh->cones[off+meetSize]; 2719 } 2720 /* Check each successive cone */ 2721 for (p = 1; p < numPoints; ++p) { 2722 PetscInt newMeetSize = 0; 2723 2724 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2725 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2726 for (c = 0; c < dof; ++c) { 2727 const PetscInt point = mesh->cones[off+c]; 2728 2729 for (m = 0; m < meetSize; ++m) { 2730 if (point == meet[i][m]) { 2731 meet[1-i][newMeetSize++] = point; 2732 break; 2733 } 2734 } 2735 } 2736 meetSize = newMeetSize; 2737 i = 1-i; 2738 } 2739 *numCoveringPoints = meetSize; 2740 *coveringPoints = meet[i]; 2741 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 2742 PetscFunctionReturn(0); 2743 } 2744 2745 /*@C 2746 DMPlexRestoreMeet - Restore 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(), DMPlexGetFullMeet(), DMPlexGetJoin() 2769 @*/ 2770 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2771 { 2772 PetscErrorCode ierr; 2773 2774 PetscFunctionBegin; 2775 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2776 if (points) PetscValidIntPointer(points,3); 2777 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 2778 PetscValidPointer(coveredPoints,5); 2779 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 2780 if (numCoveredPoints) *numCoveredPoints = 0; 2781 PetscFunctionReturn(0); 2782 } 2783 2784 /*@C 2785 DMPlexGetFullMeet - Get an array for the meet of the set of points 2786 2787 Not Collective 2788 2789 Input Parameters: 2790 + dm - The DMPlex object 2791 . numPoints - The number of input points for the meet 2792 - points - The input points 2793 2794 Output Parameters: 2795 + numCoveredPoints - The number of points in the meet 2796 - coveredPoints - The points in the meet 2797 2798 Level: intermediate 2799 2800 Fortran Notes: 2801 Since it returns an array, this routine is only available in Fortran 90, and you must 2802 include petsc.h90 in your code. 2803 2804 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2805 2806 .keywords: mesh 2807 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2808 @*/ 2809 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2810 { 2811 DM_Plex *mesh = (DM_Plex*) dm->data; 2812 PetscInt *offsets, **closures; 2813 PetscInt *meet[2]; 2814 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2815 PetscInt p, h, c, m, mc; 2816 PetscErrorCode ierr; 2817 2818 PetscFunctionBegin; 2819 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2820 PetscValidPointer(points, 2); 2821 PetscValidPointer(numCoveredPoints, 3); 2822 PetscValidPointer(coveredPoints, 4); 2823 2824 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2825 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 2826 ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 2827 mc = mesh->maxConeSize; 2828 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 2829 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 2830 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 2831 2832 for (p = 0; p < numPoints; ++p) { 2833 PetscInt closureSize; 2834 2835 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2836 2837 offsets[p*(height+2)+0] = 0; 2838 for (h = 0; h < height+1; ++h) { 2839 PetscInt pStart, pEnd, i; 2840 2841 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2842 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2843 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2844 offsets[p*(height+2)+h+1] = i; 2845 break; 2846 } 2847 } 2848 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2849 } 2850 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); 2851 } 2852 for (h = 0; h < height+1; ++h) { 2853 PetscInt dof; 2854 2855 /* Copy in cone of first point */ 2856 dof = offsets[h+1] - offsets[h]; 2857 for (meetSize = 0; meetSize < dof; ++meetSize) { 2858 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2859 } 2860 /* Check each successive cone */ 2861 for (p = 1; p < numPoints && meetSize; ++p) { 2862 PetscInt newMeetSize = 0; 2863 2864 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2865 for (c = 0; c < dof; ++c) { 2866 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2867 2868 for (m = 0; m < meetSize; ++m) { 2869 if (point == meet[i][m]) { 2870 meet[1-i][newMeetSize++] = point; 2871 break; 2872 } 2873 } 2874 } 2875 meetSize = newMeetSize; 2876 i = 1-i; 2877 } 2878 if (meetSize) break; 2879 } 2880 *numCoveredPoints = meetSize; 2881 *coveredPoints = meet[i]; 2882 for (p = 0; p < numPoints; ++p) { 2883 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2884 } 2885 ierr = PetscFree(closures);CHKERRQ(ierr); 2886 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 2887 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 2888 PetscFunctionReturn(0); 2889 } 2890 2891 /*@C 2892 DMPlexEqual - Determine if two DMs have the same topology 2893 2894 Not Collective 2895 2896 Input Parameters: 2897 + dmA - A DMPlex object 2898 - dmB - A DMPlex object 2899 2900 Output Parameters: 2901 . equal - PETSC_TRUE if the topologies are identical 2902 2903 Level: intermediate 2904 2905 Notes: 2906 We are not solving graph isomorphism, so we do not permutation. 2907 2908 .keywords: mesh 2909 .seealso: DMPlexGetCone() 2910 @*/ 2911 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 2912 { 2913 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 2914 PetscErrorCode ierr; 2915 2916 PetscFunctionBegin; 2917 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 2918 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 2919 PetscValidPointer(equal, 3); 2920 2921 *equal = PETSC_FALSE; 2922 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 2923 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 2924 if (depth != depthB) PetscFunctionReturn(0); 2925 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 2926 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 2927 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 2928 for (p = pStart; p < pEnd; ++p) { 2929 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 2930 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 2931 2932 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 2933 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 2934 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 2935 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 2936 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 2937 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 2938 if (coneSize != coneSizeB) PetscFunctionReturn(0); 2939 for (c = 0; c < coneSize; ++c) { 2940 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 2941 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 2942 } 2943 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 2944 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 2945 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 2946 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 2947 if (supportSize != supportSizeB) PetscFunctionReturn(0); 2948 for (s = 0; s < supportSize; ++s) { 2949 if (support[s] != supportB[s]) PetscFunctionReturn(0); 2950 } 2951 } 2952 *equal = PETSC_TRUE; 2953 PetscFunctionReturn(0); 2954 } 2955 2956 /*@C 2957 DMPlexGetNumFaceVertices - Returns the number of vertices on a face 2958 2959 Not Collective 2960 2961 Input Parameters: 2962 + dm - The DMPlex 2963 . cellDim - The cell dimension 2964 - numCorners - The number of vertices on a cell 2965 2966 Output Parameters: 2967 . numFaceVertices - The number of vertices on a face 2968 2969 Level: developer 2970 2971 Notes: 2972 Of course this can only work for a restricted set of symmetric shapes 2973 2974 .seealso: DMPlexGetCone() 2975 @*/ 2976 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 2977 { 2978 MPI_Comm comm; 2979 PetscErrorCode ierr; 2980 2981 PetscFunctionBegin; 2982 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2983 PetscValidPointer(numFaceVertices,3); 2984 switch (cellDim) { 2985 case 0: 2986 *numFaceVertices = 0; 2987 break; 2988 case 1: 2989 *numFaceVertices = 1; 2990 break; 2991 case 2: 2992 switch (numCorners) { 2993 case 3: /* triangle */ 2994 *numFaceVertices = 2; /* Edge has 2 vertices */ 2995 break; 2996 case 4: /* quadrilateral */ 2997 *numFaceVertices = 2; /* Edge has 2 vertices */ 2998 break; 2999 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 3000 *numFaceVertices = 3; /* Edge has 3 vertices */ 3001 break; 3002 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 3003 *numFaceVertices = 3; /* Edge has 3 vertices */ 3004 break; 3005 default: 3006 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 3007 } 3008 break; 3009 case 3: 3010 switch (numCorners) { 3011 case 4: /* tetradehdron */ 3012 *numFaceVertices = 3; /* Face has 3 vertices */ 3013 break; 3014 case 6: /* tet cohesive cells */ 3015 *numFaceVertices = 4; /* Face has 4 vertices */ 3016 break; 3017 case 8: /* hexahedron */ 3018 *numFaceVertices = 4; /* Face has 4 vertices */ 3019 break; 3020 case 9: /* tet cohesive Lagrange cells */ 3021 *numFaceVertices = 6; /* Face has 6 vertices */ 3022 break; 3023 case 10: /* quadratic tetrahedron */ 3024 *numFaceVertices = 6; /* Face has 6 vertices */ 3025 break; 3026 case 12: /* hex cohesive Lagrange cells */ 3027 *numFaceVertices = 6; /* Face has 6 vertices */ 3028 break; 3029 case 18: /* quadratic tet cohesive Lagrange cells */ 3030 *numFaceVertices = 6; /* Face has 6 vertices */ 3031 break; 3032 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 3033 *numFaceVertices = 9; /* Face has 9 vertices */ 3034 break; 3035 default: 3036 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 3037 } 3038 break; 3039 default: 3040 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 3041 } 3042 PetscFunctionReturn(0); 3043 } 3044 3045 /*@ 3046 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 3047 3048 Not Collective 3049 3050 Input Parameter: 3051 . dm - The DMPlex object 3052 3053 Output Parameter: 3054 . depthLabel - The DMLabel recording point depth 3055 3056 Level: developer 3057 3058 .keywords: mesh, points 3059 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 3060 @*/ 3061 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 3062 { 3063 PetscErrorCode ierr; 3064 3065 PetscFunctionBegin; 3066 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3067 PetscValidPointer(depthLabel, 2); 3068 if (!dm->depthLabel) {ierr = DMGetLabel(dm, "depth", &dm->depthLabel);CHKERRQ(ierr);} 3069 *depthLabel = dm->depthLabel; 3070 PetscFunctionReturn(0); 3071 } 3072 3073 /*@ 3074 DMPlexGetDepth - Get the depth of the DAG representing this mesh 3075 3076 Not Collective 3077 3078 Input Parameter: 3079 . dm - The DMPlex object 3080 3081 Output Parameter: 3082 . depth - The number of strata (breadth first levels) in the DAG 3083 3084 Level: developer 3085 3086 .keywords: mesh, points 3087 .seealso: DMPlexGetDepthLabel(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 3088 @*/ 3089 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 3090 { 3091 DMLabel label; 3092 PetscInt d = 0; 3093 PetscErrorCode ierr; 3094 3095 PetscFunctionBegin; 3096 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3097 PetscValidPointer(depth, 2); 3098 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3099 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 3100 *depth = d-1; 3101 PetscFunctionReturn(0); 3102 } 3103 3104 /*@ 3105 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 3106 3107 Not Collective 3108 3109 Input Parameters: 3110 + dm - The DMPlex object 3111 - stratumValue - The requested depth 3112 3113 Output Parameters: 3114 + start - The first point at this depth 3115 - end - One beyond the last point at this depth 3116 3117 Level: developer 3118 3119 .keywords: mesh, points 3120 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 3121 @*/ 3122 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 3123 { 3124 DMLabel label; 3125 PetscInt pStart, pEnd; 3126 PetscErrorCode ierr; 3127 3128 PetscFunctionBegin; 3129 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3130 if (start) {PetscValidPointer(start, 3); *start = 0;} 3131 if (end) {PetscValidPointer(end, 4); *end = 0;} 3132 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3133 if (pStart == pEnd) PetscFunctionReturn(0); 3134 if (stratumValue < 0) { 3135 if (start) *start = pStart; 3136 if (end) *end = pEnd; 3137 PetscFunctionReturn(0); 3138 } 3139 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3140 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 3141 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 3142 PetscFunctionReturn(0); 3143 } 3144 3145 /*@ 3146 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 3147 3148 Not Collective 3149 3150 Input Parameters: 3151 + dm - The DMPlex object 3152 - stratumValue - The requested height 3153 3154 Output Parameters: 3155 + start - The first point at this height 3156 - end - One beyond the last point at this height 3157 3158 Level: developer 3159 3160 .keywords: mesh, points 3161 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 3162 @*/ 3163 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 3164 { 3165 DMLabel label; 3166 PetscInt depth, pStart, pEnd; 3167 PetscErrorCode ierr; 3168 3169 PetscFunctionBegin; 3170 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3171 if (start) {PetscValidPointer(start, 3); *start = 0;} 3172 if (end) {PetscValidPointer(end, 4); *end = 0;} 3173 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3174 if (pStart == pEnd) PetscFunctionReturn(0); 3175 if (stratumValue < 0) { 3176 if (start) *start = pStart; 3177 if (end) *end = pEnd; 3178 PetscFunctionReturn(0); 3179 } 3180 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3181 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 3182 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 3183 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 3184 PetscFunctionReturn(0); 3185 } 3186 3187 /* Set the number of dof on each point and separate by fields */ 3188 static PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 3189 { 3190 PetscInt *pMax; 3191 PetscInt depth, cellHeight, pStart = 0, pEnd = 0; 3192 PetscInt Nf, p, d, dep, f; 3193 PetscBool *isFE; 3194 PetscErrorCode ierr; 3195 3196 PetscFunctionBegin; 3197 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 3198 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 3199 for (f = 0; f < numFields; ++f) { 3200 PetscObject obj; 3201 PetscClassId id; 3202 3203 isFE[f] = PETSC_FALSE; 3204 if (f >= Nf) continue; 3205 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 3206 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 3207 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 3208 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 3209 } 3210 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 3211 if (numFields > 0) { 3212 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 3213 if (numComp) { 3214 for (f = 0; f < numFields; ++f) { 3215 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 3216 if (isFE[f]) { 3217 PetscFE fe; 3218 PetscDualSpace dspace; 3219 const PetscInt ***perms; 3220 const PetscScalar ***flips; 3221 const PetscInt *numDof; 3222 3223 ierr = DMGetField(dm,f,(PetscObject *) &fe);CHKERRQ(ierr); 3224 ierr = PetscFEGetDualSpace(fe,&dspace);CHKERRQ(ierr); 3225 ierr = PetscDualSpaceGetSymmetries(dspace,&perms,&flips);CHKERRQ(ierr); 3226 ierr = PetscDualSpaceGetNumDof(dspace,&numDof);CHKERRQ(ierr); 3227 if (perms || flips) { 3228 DM K; 3229 DMLabel depthLabel; 3230 PetscInt depth, h; 3231 PetscSectionSym sym; 3232 3233 ierr = PetscDualSpaceGetDM(dspace,&K);CHKERRQ(ierr); 3234 ierr = DMPlexGetDepthLabel(dm,&depthLabel);CHKERRQ(ierr); 3235 ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr); 3236 ierr = PetscSectionSymCreateLabel(PetscObjectComm((PetscObject)*section),depthLabel,&sym);CHKERRQ(ierr); 3237 for (h = 0; h <= depth; h++) { 3238 PetscDualSpace hspace; 3239 PetscInt kStart, kEnd; 3240 PetscInt kConeSize; 3241 const PetscInt **perms0 = NULL; 3242 const PetscScalar **flips0 = NULL; 3243 3244 ierr = PetscDualSpaceGetHeightSubspace(dspace,h,&hspace);CHKERRQ(ierr); 3245 ierr = DMPlexGetHeightStratum(K,h,&kStart,&kEnd);CHKERRQ(ierr); 3246 if (!hspace) continue; 3247 ierr = PetscDualSpaceGetSymmetries(hspace,&perms,&flips);CHKERRQ(ierr); 3248 if (perms) perms0 = perms[0]; 3249 if (flips) flips0 = flips[0]; 3250 if (!(perms0 || flips0)) continue; 3251 ierr = DMPlexGetConeSize(K,kStart,&kConeSize);CHKERRQ(ierr); 3252 ierr = PetscSectionSymLabelSetStratum(sym,depth - h,numDof[depth - h],-kConeSize,kConeSize,PETSC_USE_POINTER,perms0 ? &perms0[-kConeSize] : NULL,flips0 ? &flips0[-kConeSize] : NULL);CHKERRQ(ierr); 3253 } 3254 ierr = PetscSectionSetFieldSym(*section,f,sym);CHKERRQ(ierr); 3255 ierr = PetscSectionSymDestroy(&sym);CHKERRQ(ierr); 3256 } 3257 } 3258 } 3259 } 3260 } 3261 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3262 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 3263 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3264 ierr = PetscMalloc1(depth+1,&pMax);CHKERRQ(ierr); 3265 ierr = DMPlexGetHybridBounds(dm, depth >= 0 ? &pMax[depth] : NULL, depth>1 ? &pMax[depth-1] : NULL, depth>2 ? &pMax[1] : NULL, &pMax[0]);CHKERRQ(ierr); 3266 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 3267 for (dep = 0; dep <= depth - cellHeight; ++dep) { 3268 d = dim == depth ? dep : (!dep ? 0 : dim); 3269 ierr = DMPlexGetDepthStratum(dm, dep, &pStart, &pEnd);CHKERRQ(ierr); 3270 pMax[dep] = pMax[dep] < 0 ? pEnd : pMax[dep]; 3271 for (p = pStart; p < pEnd; ++p) { 3272 PetscInt tot = 0; 3273 3274 for (f = 0; f < numFields; ++f) { 3275 if (isFE[f] && p >= pMax[dep]) continue; 3276 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 3277 tot += numDof[f*(dim+1)+d]; 3278 } 3279 ierr = PetscSectionSetDof(*section, p, tot);CHKERRQ(ierr); 3280 } 3281 } 3282 ierr = PetscFree(pMax);CHKERRQ(ierr); 3283 ierr = PetscFree(isFE);CHKERRQ(ierr); 3284 PetscFunctionReturn(0); 3285 } 3286 3287 /* Set the number of dof on each point and separate by fields 3288 If bcComps is NULL or the IS is NULL, constrain every dof on the point 3289 */ 3290 static PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC, const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 3291 { 3292 PetscInt numFields; 3293 PetscInt bc; 3294 PetscSection aSec; 3295 PetscErrorCode ierr; 3296 3297 PetscFunctionBegin; 3298 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3299 for (bc = 0; bc < numBC; ++bc) { 3300 PetscInt field = 0; 3301 const PetscInt *comp; 3302 const PetscInt *idx; 3303 PetscInt Nc = -1, n, i; 3304 3305 if (numFields) field = bcField[bc]; 3306 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 3307 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3308 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 3309 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3310 for (i = 0; i < n; ++i) { 3311 const PetscInt p = idx[i]; 3312 PetscInt numConst; 3313 3314 if (numFields) { 3315 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 3316 } else { 3317 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 3318 } 3319 /* If Nc < 0, constrain every dof on the point */ 3320 if (Nc > 0) numConst = PetscMin(numConst, Nc); 3321 if (numFields) {ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr);} 3322 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 3323 } 3324 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3325 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3326 } 3327 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 3328 if (aSec) { 3329 PetscInt aStart, aEnd, a; 3330 3331 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 3332 for (a = aStart; a < aEnd; a++) { 3333 PetscInt dof, f; 3334 3335 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 3336 if (dof) { 3337 /* if there are point-to-point constraints, then all dofs are constrained */ 3338 ierr = PetscSectionGetDof(section, a, &dof);CHKERRQ(ierr); 3339 ierr = PetscSectionSetConstraintDof(section, a, dof);CHKERRQ(ierr); 3340 for (f = 0; f < numFields; f++) { 3341 ierr = PetscSectionGetFieldDof(section, a, f, &dof);CHKERRQ(ierr); 3342 ierr = PetscSectionSetFieldConstraintDof(section, a, f, dof);CHKERRQ(ierr); 3343 } 3344 } 3345 } 3346 } 3347 PetscFunctionReturn(0); 3348 } 3349 3350 /* Set the constrained field indices on each point 3351 If bcComps is NULL or the IS is NULL, constrain every dof on the point 3352 */ 3353 static PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt numBC,const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 3354 { 3355 PetscSection aSec; 3356 PetscInt *indices; 3357 PetscInt numFields, cdof, maxDof = 0, pStart, pEnd, p, bc, f, d; 3358 PetscErrorCode ierr; 3359 3360 PetscFunctionBegin; 3361 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3362 if (!numFields) PetscFunctionReturn(0); 3363 /* Initialize all field indices to -1 */ 3364 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3365 for (p = pStart; p < pEnd; ++p) {ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); maxDof = PetscMax(maxDof, cdof);} 3366 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 3367 for (d = 0; d < maxDof; ++d) indices[d] = -1; 3368 for (p = pStart; p < pEnd; ++p) for (f = 0; f < numFields; ++f) {ierr = PetscSectionSetFieldConstraintIndices(section, p, f, indices);CHKERRQ(ierr);} 3369 /* Handle BC constraints */ 3370 for (bc = 0; bc < numBC; ++bc) { 3371 const PetscInt field = bcField[bc]; 3372 const PetscInt *comp, *idx; 3373 PetscInt Nc = -1, n, i; 3374 3375 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 3376 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3377 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 3378 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3379 for (i = 0; i < n; ++i) { 3380 const PetscInt p = idx[i]; 3381 const PetscInt *find; 3382 PetscInt fdof, fcdof, c; 3383 3384 ierr = PetscSectionGetFieldDof(section, p, field, &fdof);CHKERRQ(ierr); 3385 if (!fdof) continue; 3386 if (Nc < 0) { 3387 for (d = 0; d < fdof; ++d) indices[d] = d; 3388 fcdof = fdof; 3389 } else { 3390 ierr = PetscSectionGetFieldConstraintDof(section, p, field, &fcdof);CHKERRQ(ierr); 3391 ierr = PetscSectionGetFieldConstraintIndices(section, p, field, &find);CHKERRQ(ierr); 3392 for (d = 0; d < fcdof; ++d) {if (find[d] < 0) break; indices[d] = find[d];} 3393 for (c = 0; c < Nc; ++c) indices[d++] = comp[c]; 3394 ierr = PetscSortRemoveDupsInt(&d, indices);CHKERRQ(ierr); 3395 for (c = d; c < fcdof; ++c) indices[c] = -1; 3396 fcdof = d; 3397 } 3398 ierr = PetscSectionSetFieldConstraintDof(section, p, field, fcdof);CHKERRQ(ierr); 3399 ierr = PetscSectionSetFieldConstraintIndices(section, p, field, indices);CHKERRQ(ierr); 3400 } 3401 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3402 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3403 } 3404 /* Handle anchors */ 3405 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 3406 if (aSec) { 3407 PetscInt aStart, aEnd, a; 3408 3409 for (d = 0; d < maxDof; ++d) indices[d] = d; 3410 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 3411 for (a = aStart; a < aEnd; a++) { 3412 PetscInt dof, f; 3413 3414 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 3415 if (dof) { 3416 /* if there are point-to-point constraints, then all dofs are constrained */ 3417 for (f = 0; f < numFields; f++) { 3418 ierr = PetscSectionSetFieldConstraintIndices(section, a, f, indices);CHKERRQ(ierr); 3419 } 3420 } 3421 } 3422 } 3423 ierr = PetscFree(indices);CHKERRQ(ierr); 3424 PetscFunctionReturn(0); 3425 } 3426 3427 /* Set the constrained indices on each point */ 3428 static PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 3429 { 3430 PetscInt *indices; 3431 PetscInt numFields, maxDof, pStart, pEnd, p, f, d; 3432 PetscErrorCode ierr; 3433 3434 PetscFunctionBegin; 3435 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3436 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 3437 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3438 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 3439 for (d = 0; d < maxDof; ++d) indices[d] = -1; 3440 for (p = pStart; p < pEnd; ++p) { 3441 PetscInt cdof, d; 3442 3443 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 3444 if (cdof) { 3445 if (numFields) { 3446 PetscInt numConst = 0, foff = 0; 3447 3448 for (f = 0; f < numFields; ++f) { 3449 const PetscInt *find; 3450 PetscInt fcdof, fdof; 3451 3452 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 3453 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 3454 /* Change constraint numbering from field component to local dof number */ 3455 ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &find);CHKERRQ(ierr); 3456 for (d = 0; d < fcdof; ++d) indices[numConst+d] = find[d] + foff; 3457 numConst += fcdof; 3458 foff += fdof; 3459 } 3460 if (cdof != numConst) {ierr = PetscSectionSetConstraintDof(section, p, numConst);CHKERRQ(ierr);} 3461 } else { 3462 for (d = 0; d < cdof; ++d) indices[d] = d; 3463 } 3464 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 3465 } 3466 } 3467 ierr = PetscFree(indices);CHKERRQ(ierr); 3468 PetscFunctionReturn(0); 3469 } 3470 3471 /*@C 3472 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 3473 3474 Not Collective 3475 3476 Input Parameters: 3477 + dm - The DMPlex object 3478 . dim - The spatial dimension of the problem 3479 . numFields - The number of fields in the problem 3480 . numComp - An array of size numFields that holds the number of components for each field 3481 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 3482 . numBC - The number of boundary conditions 3483 . bcField - An array of size numBC giving the field number for each boundry condition 3484 . bcComps - [Optional] An array of size numBC giving an IS holding the field components to which each boundary condition applies 3485 . bcPoints - An array of size numBC giving an IS holding the Plex points to which each boundary condition applies 3486 - perm - Optional permutation of the chart, or NULL 3487 3488 Output Parameter: 3489 . section - The PetscSection object 3490 3491 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 3492 number of dof for field 0 on each edge. 3493 3494 The chart permutation is the same one set using PetscSectionSetPermutation() 3495 3496 Level: developer 3497 3498 Fortran Notes: 3499 A Fortran 90 version is available as DMPlexCreateSectionF90() 3500 3501 .keywords: mesh, elements 3502 .seealso: DMPlexCreate(), PetscSectionCreate(), PetscSectionSetPermutation() 3503 @*/ 3504 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) 3505 { 3506 PetscSection aSec; 3507 PetscErrorCode ierr; 3508 3509 PetscFunctionBegin; 3510 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 3511 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3512 if (perm) {ierr = PetscSectionSetPermutation(*section, perm);CHKERRQ(ierr);} 3513 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3514 ierr = DMPlexGetAnchors(dm,&aSec,NULL);CHKERRQ(ierr); 3515 if (numBC || aSec) { 3516 ierr = DMPlexCreateSectionBCIndicesField(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3517 ierr = DMPlexCreateSectionBCIndices(dm, *section);CHKERRQ(ierr); 3518 } 3519 ierr = PetscSectionViewFromOptions(*section,NULL,"-section_view");CHKERRQ(ierr); 3520 PetscFunctionReturn(0); 3521 } 3522 3523 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 3524 { 3525 PetscSection section, s; 3526 Mat m; 3527 PetscInt maxHeight; 3528 PetscErrorCode ierr; 3529 3530 PetscFunctionBegin; 3531 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 3532 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 3533 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 3534 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 3535 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 3536 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 3537 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 3538 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 3539 ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr); 3540 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 3541 ierr = MatDestroy(&m);CHKERRQ(ierr); 3542 PetscFunctionReturn(0); 3543 } 3544 3545 /*@C 3546 DMPlexGetConeSection - Return a section which describes the layout of cone data 3547 3548 Not Collective 3549 3550 Input Parameters: 3551 . dm - The DMPlex object 3552 3553 Output Parameter: 3554 . section - The PetscSection object 3555 3556 Level: developer 3557 3558 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 3559 @*/ 3560 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 3561 { 3562 DM_Plex *mesh = (DM_Plex*) dm->data; 3563 3564 PetscFunctionBegin; 3565 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3566 if (section) *section = mesh->coneSection; 3567 PetscFunctionReturn(0); 3568 } 3569 3570 /*@C 3571 DMPlexGetSupportSection - Return a section which describes the layout of support data 3572 3573 Not Collective 3574 3575 Input Parameters: 3576 . dm - The DMPlex object 3577 3578 Output Parameter: 3579 . section - The PetscSection object 3580 3581 Level: developer 3582 3583 .seealso: DMPlexGetConeSection() 3584 @*/ 3585 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 3586 { 3587 DM_Plex *mesh = (DM_Plex*) dm->data; 3588 3589 PetscFunctionBegin; 3590 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3591 if (section) *section = mesh->supportSection; 3592 PetscFunctionReturn(0); 3593 } 3594 3595 /*@C 3596 DMPlexGetCones - Return cone data 3597 3598 Not Collective 3599 3600 Input Parameters: 3601 . dm - The DMPlex object 3602 3603 Output Parameter: 3604 . cones - The cone for each point 3605 3606 Level: developer 3607 3608 .seealso: DMPlexGetConeSection() 3609 @*/ 3610 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 3611 { 3612 DM_Plex *mesh = (DM_Plex*) dm->data; 3613 3614 PetscFunctionBegin; 3615 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3616 if (cones) *cones = mesh->cones; 3617 PetscFunctionReturn(0); 3618 } 3619 3620 /*@C 3621 DMPlexGetConeOrientations - Return cone orientation data 3622 3623 Not Collective 3624 3625 Input Parameters: 3626 . dm - The DMPlex object 3627 3628 Output Parameter: 3629 . coneOrientations - The cone orientation for each point 3630 3631 Level: developer 3632 3633 .seealso: DMPlexGetConeSection() 3634 @*/ 3635 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 3636 { 3637 DM_Plex *mesh = (DM_Plex*) dm->data; 3638 3639 PetscFunctionBegin; 3640 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3641 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 3642 PetscFunctionReturn(0); 3643 } 3644 3645 /******************************** FEM Support **********************************/ 3646 3647 PetscErrorCode DMPlexCreateSpectralClosurePermutation(DM dm, PetscInt point, PetscSection section) 3648 { 3649 DMLabel label; 3650 PetscInt *perm; 3651 PetscInt dim, depth, eStart, k, Nf, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 3652 PetscErrorCode ierr; 3653 3654 PetscFunctionBegin; 3655 if (point < 0) {ierr = DMPlexGetDepthStratum(dm, 1, &point, NULL);CHKERRQ(ierr);} 3656 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3657 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3658 ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); 3659 if (depth == 1) {eStart = point;} 3660 else if (depth == dim) { 3661 const PetscInt *cone; 3662 3663 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3664 eStart = cone[0]; 3665 } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering", point, depth); 3666 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3667 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 3668 if (dim <= 1) PetscFunctionReturn(0); 3669 for (f = 0; f < Nf; ++f) { 3670 /* An order k SEM disc has k-1 dofs on an edge */ 3671 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3672 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3673 k = k/Nc + 1; 3674 size += PetscPowInt(k+1, dim)*Nc; 3675 } 3676 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 3677 for (f = 0; f < Nf; ++f) { 3678 switch (dim) { 3679 case 2: 3680 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 3681 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3682 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3683 k = k/Nc + 1; 3684 /* The SEM order is 3685 3686 v_lb, {e_b}, v_rb, 3687 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 3688 v_lt, reverse {e_t}, v_rt 3689 */ 3690 { 3691 const PetscInt of = 0; 3692 const PetscInt oeb = of + PetscSqr(k-1); 3693 const PetscInt oer = oeb + (k-1); 3694 const PetscInt oet = oer + (k-1); 3695 const PetscInt oel = oet + (k-1); 3696 const PetscInt ovlb = oel + (k-1); 3697 const PetscInt ovrb = ovlb + 1; 3698 const PetscInt ovrt = ovrb + 1; 3699 const PetscInt ovlt = ovrt + 1; 3700 PetscInt o; 3701 3702 /* bottom */ 3703 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 3704 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3705 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 3706 /* middle */ 3707 for (i = 0; i < k-1; ++i) { 3708 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 3709 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; 3710 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 3711 } 3712 /* top */ 3713 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 3714 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3715 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 3716 foffset = offset; 3717 } 3718 break; 3719 case 3: 3720 /* The original hex closure is 3721 3722 {c, 3723 f_b, f_t, f_f, f_b, f_r, f_l, 3724 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 3725 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 3726 */ 3727 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3728 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3729 k = k/Nc + 1; 3730 /* The SEM order is 3731 Bottom Slice 3732 v_blf, {e^{(k-1)-n}_bf}, v_brf, 3733 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 3734 v_blb, {e_bb}, v_brb, 3735 3736 Middle Slice (j) 3737 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 3738 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 3739 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 3740 3741 Top Slice 3742 v_tlf, {e_tf}, v_trf, 3743 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 3744 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 3745 */ 3746 { 3747 const PetscInt oc = 0; 3748 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 3749 const PetscInt oft = ofb + PetscSqr(k-1); 3750 const PetscInt off = oft + PetscSqr(k-1); 3751 const PetscInt ofk = off + PetscSqr(k-1); 3752 const PetscInt ofr = ofk + PetscSqr(k-1); 3753 const PetscInt ofl = ofr + PetscSqr(k-1); 3754 const PetscInt oebl = ofl + PetscSqr(k-1); 3755 const PetscInt oebb = oebl + (k-1); 3756 const PetscInt oebr = oebb + (k-1); 3757 const PetscInt oebf = oebr + (k-1); 3758 const PetscInt oetf = oebf + (k-1); 3759 const PetscInt oetr = oetf + (k-1); 3760 const PetscInt oetb = oetr + (k-1); 3761 const PetscInt oetl = oetb + (k-1); 3762 const PetscInt oerf = oetl + (k-1); 3763 const PetscInt oelf = oerf + (k-1); 3764 const PetscInt oelb = oelf + (k-1); 3765 const PetscInt oerb = oelb + (k-1); 3766 const PetscInt ovblf = oerb + (k-1); 3767 const PetscInt ovblb = ovblf + 1; 3768 const PetscInt ovbrb = ovblb + 1; 3769 const PetscInt ovbrf = ovbrb + 1; 3770 const PetscInt ovtlf = ovbrf + 1; 3771 const PetscInt ovtrf = ovtlf + 1; 3772 const PetscInt ovtrb = ovtrf + 1; 3773 const PetscInt ovtlb = ovtrb + 1; 3774 PetscInt o, n; 3775 3776 /* Bottom Slice */ 3777 /* bottom */ 3778 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 3779 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3780 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 3781 /* middle */ 3782 for (i = 0; i < k-1; ++i) { 3783 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 3784 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;} 3785 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 3786 } 3787 /* top */ 3788 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 3789 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3790 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 3791 3792 /* Middle Slice */ 3793 for (j = 0; j < k-1; ++j) { 3794 /* bottom */ 3795 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 3796 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; 3797 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 3798 /* middle */ 3799 for (i = 0; i < k-1; ++i) { 3800 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 3801 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; 3802 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 3803 } 3804 /* top */ 3805 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 3806 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; 3807 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 3808 } 3809 3810 /* Top Slice */ 3811 /* bottom */ 3812 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 3813 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3814 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 3815 /* middle */ 3816 for (i = 0; i < k-1; ++i) { 3817 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 3818 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 3819 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 3820 } 3821 /* top */ 3822 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 3823 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3824 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 3825 3826 foffset = offset; 3827 } 3828 break; 3829 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", dim); 3830 } 3831 } 3832 if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 3833 /* Check permutation */ 3834 { 3835 PetscInt *check; 3836 3837 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 3838 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]);} 3839 for (i = 0; i < size; ++i) check[perm[i]] = i; 3840 for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 3841 ierr = PetscFree(check);CHKERRQ(ierr); 3842 } 3843 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 3844 PetscFunctionReturn(0); 3845 } 3846 3847 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 3848 { 3849 PetscDS prob; 3850 PetscInt depth, Nf, h; 3851 DMLabel label; 3852 PetscErrorCode ierr; 3853 3854 PetscFunctionBeginHot; 3855 prob = dm->prob; 3856 Nf = prob->Nf; 3857 label = dm->depthLabel; 3858 *dspace = NULL; 3859 if (field < Nf) { 3860 PetscObject disc = prob->disc[field]; 3861 3862 if (disc->classid == PETSCFE_CLASSID) { 3863 PetscDualSpace dsp; 3864 3865 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 3866 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 3867 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 3868 h = depth - 1 - h; 3869 if (h) { 3870 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 3871 } else { 3872 *dspace = dsp; 3873 } 3874 } 3875 } 3876 PetscFunctionReturn(0); 3877 } 3878 3879 3880 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3881 { 3882 PetscScalar *array, *vArray; 3883 const PetscInt *cone, *coneO; 3884 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 3885 PetscErrorCode ierr; 3886 3887 PetscFunctionBeginHot; 3888 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3889 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3890 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3891 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3892 if (!values || !*values) { 3893 if ((point >= pStart) && (point < pEnd)) { 3894 PetscInt dof; 3895 3896 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3897 size += dof; 3898 } 3899 for (p = 0; p < numPoints; ++p) { 3900 const PetscInt cp = cone[p]; 3901 PetscInt dof; 3902 3903 if ((cp < pStart) || (cp >= pEnd)) continue; 3904 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3905 size += dof; 3906 } 3907 if (!values) { 3908 if (csize) *csize = size; 3909 PetscFunctionReturn(0); 3910 } 3911 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 3912 } else { 3913 array = *values; 3914 } 3915 size = 0; 3916 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3917 if ((point >= pStart) && (point < pEnd)) { 3918 PetscInt dof, off, d; 3919 PetscScalar *varr; 3920 3921 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3922 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3923 varr = &vArray[off]; 3924 for (d = 0; d < dof; ++d, ++offset) { 3925 array[offset] = varr[d]; 3926 } 3927 size += dof; 3928 } 3929 for (p = 0; p < numPoints; ++p) { 3930 const PetscInt cp = cone[p]; 3931 PetscInt o = coneO[p]; 3932 PetscInt dof, off, d; 3933 PetscScalar *varr; 3934 3935 if ((cp < pStart) || (cp >= pEnd)) continue; 3936 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3937 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 3938 varr = &vArray[off]; 3939 if (o >= 0) { 3940 for (d = 0; d < dof; ++d, ++offset) { 3941 array[offset] = varr[d]; 3942 } 3943 } else { 3944 for (d = dof-1; d >= 0; --d, ++offset) { 3945 array[offset] = varr[d]; 3946 } 3947 } 3948 size += dof; 3949 } 3950 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3951 if (!*values) { 3952 if (csize) *csize = size; 3953 *values = array; 3954 } else { 3955 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 3956 *csize = size; 3957 } 3958 PetscFunctionReturn(0); 3959 } 3960 3961 static PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 3962 { 3963 const PetscInt *cla; 3964 PetscInt np, *pts = NULL; 3965 PetscErrorCode ierr; 3966 3967 PetscFunctionBeginHot; 3968 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 3969 if (!*clPoints) { 3970 PetscInt pStart, pEnd, p, q; 3971 3972 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3973 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 3974 /* Compress out points not in the section */ 3975 for (p = 0, q = 0; p < np; p++) { 3976 PetscInt r = pts[2*p]; 3977 if ((r >= pStart) && (r < pEnd)) { 3978 pts[q*2] = r; 3979 pts[q*2+1] = pts[2*p+1]; 3980 ++q; 3981 } 3982 } 3983 np = q; 3984 cla = NULL; 3985 } else { 3986 PetscInt dof, off; 3987 3988 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 3989 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 3990 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 3991 np = dof/2; 3992 pts = (PetscInt *) &cla[off]; 3993 } 3994 *numPoints = np; 3995 *points = pts; 3996 *clp = cla; 3997 3998 PetscFunctionReturn(0); 3999 } 4000 4001 static PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 4002 { 4003 PetscErrorCode ierr; 4004 4005 PetscFunctionBeginHot; 4006 if (!*clPoints) { 4007 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 4008 } else { 4009 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 4010 } 4011 *numPoints = 0; 4012 *points = NULL; 4013 *clSec = NULL; 4014 *clPoints = NULL; 4015 *clp = NULL; 4016 PetscFunctionReturn(0); 4017 } 4018 4019 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[]) 4020 { 4021 PetscInt offset = 0, p; 4022 const PetscInt **perms = NULL; 4023 const PetscScalar **flips = NULL; 4024 PetscErrorCode ierr; 4025 4026 PetscFunctionBeginHot; 4027 *size = 0; 4028 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4029 for (p = 0; p < numPoints; p++) { 4030 const PetscInt point = points[2*p]; 4031 const PetscInt *perm = perms ? perms[p] : NULL; 4032 const PetscScalar *flip = flips ? flips[p] : NULL; 4033 PetscInt dof, off, d; 4034 const PetscScalar *varr; 4035 4036 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4037 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4038 varr = &vArray[off]; 4039 if (clperm) { 4040 if (perm) { 4041 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 4042 } else { 4043 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 4044 } 4045 if (flip) { 4046 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 4047 } 4048 } else { 4049 if (perm) { 4050 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 4051 } else { 4052 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 4053 } 4054 if (flip) { 4055 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 4056 } 4057 } 4058 offset += dof; 4059 } 4060 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4061 *size = offset; 4062 PetscFunctionReturn(0); 4063 } 4064 4065 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[]) 4066 { 4067 PetscInt offset = 0, f; 4068 PetscErrorCode ierr; 4069 4070 PetscFunctionBeginHot; 4071 *size = 0; 4072 for (f = 0; f < numFields; ++f) { 4073 PetscInt p; 4074 const PetscInt **perms = NULL; 4075 const PetscScalar **flips = NULL; 4076 4077 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4078 for (p = 0; p < numPoints; p++) { 4079 const PetscInt point = points[2*p]; 4080 PetscInt fdof, foff, b; 4081 const PetscScalar *varr; 4082 const PetscInt *perm = perms ? perms[p] : NULL; 4083 const PetscScalar *flip = flips ? flips[p] : NULL; 4084 4085 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4086 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4087 varr = &vArray[foff]; 4088 if (clperm) { 4089 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 4090 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 4091 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 4092 } else { 4093 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 4094 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 4095 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 4096 } 4097 offset += fdof; 4098 } 4099 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4100 } 4101 *size = offset; 4102 PetscFunctionReturn(0); 4103 } 4104 4105 /*@C 4106 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 4107 4108 Not collective 4109 4110 Input Parameters: 4111 + dm - The DM 4112 . section - The section describing the layout in v, or NULL to use the default section 4113 . v - The local vector 4114 . point - The point in the DM 4115 . csize - The size of the input values array, or NULL 4116 - values - An array to use for the values, or NULL to have it allocated automatically 4117 4118 Output Parameters: 4119 + csize - The number of values in the closure 4120 - values - The array of values. If the user provided NULL, it is a borrowed array and should not be freed 4121 4122 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 4123 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 4124 $ assembly function, and a user may already have allocated storage for this operation. 4125 $ 4126 $ A typical use could be 4127 $ 4128 $ values = NULL; 4129 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4130 $ for (cl = 0; cl < clSize; ++cl) { 4131 $ <Compute on closure> 4132 $ } 4133 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4134 $ 4135 $ or 4136 $ 4137 $ PetscMalloc1(clMaxSize, &values); 4138 $ for (p = pStart; p < pEnd; ++p) { 4139 $ clSize = clMaxSize; 4140 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4141 $ for (cl = 0; cl < clSize; ++cl) { 4142 $ <Compute on closure> 4143 $ } 4144 $ } 4145 $ PetscFree(values); 4146 4147 Fortran Notes: 4148 Since it returns an array, this routine is only available in Fortran 90, and you must 4149 include petsc.h90 in your code. 4150 4151 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4152 4153 Level: intermediate 4154 4155 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4156 @*/ 4157 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4158 { 4159 PetscSection clSection; 4160 IS clPoints; 4161 PetscScalar *array; 4162 const PetscScalar *vArray; 4163 PetscInt *points = NULL; 4164 const PetscInt *clp, *perm; 4165 PetscInt depth, numFields, numPoints, size; 4166 PetscErrorCode ierr; 4167 4168 PetscFunctionBeginHot; 4169 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4170 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4171 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4172 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4173 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4174 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4175 if (depth == 1 && numFields < 2) { 4176 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 4177 PetscFunctionReturn(0); 4178 } 4179 /* Get points */ 4180 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4181 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &perm);CHKERRQ(ierr); 4182 /* Get array */ 4183 if (!values || !*values) { 4184 PetscInt asize = 0, dof, p; 4185 4186 for (p = 0; p < numPoints*2; p += 2) { 4187 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4188 asize += dof; 4189 } 4190 if (!values) { 4191 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4192 if (csize) *csize = asize; 4193 PetscFunctionReturn(0); 4194 } 4195 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 4196 } else { 4197 array = *values; 4198 } 4199 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 4200 /* Get values */ 4201 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 4202 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, array);CHKERRQ(ierr);} 4203 /* Cleanup points */ 4204 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4205 /* Cleanup array */ 4206 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 4207 if (!*values) { 4208 if (csize) *csize = size; 4209 *values = array; 4210 } else { 4211 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 4212 *csize = size; 4213 } 4214 PetscFunctionReturn(0); 4215 } 4216 4217 /*@C 4218 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 4219 4220 Not collective 4221 4222 Input Parameters: 4223 + dm - The DM 4224 . section - The section describing the layout in v, or NULL to use the default section 4225 . v - The local vector 4226 . point - The point in the DM 4227 . csize - The number of values in the closure, or NULL 4228 - values - The array of values, which is a borrowed array and should not be freed 4229 4230 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 4231 4232 Fortran Notes: 4233 Since it returns an array, this routine is only available in Fortran 90, and you must 4234 include petsc.h90 in your code. 4235 4236 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4237 4238 Level: intermediate 4239 4240 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4241 @*/ 4242 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4243 { 4244 PetscInt size = 0; 4245 PetscErrorCode ierr; 4246 4247 PetscFunctionBegin; 4248 /* Should work without recalculating size */ 4249 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 4250 *values = NULL; 4251 PetscFunctionReturn(0); 4252 } 4253 4254 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 4255 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 4256 4257 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[]) 4258 { 4259 PetscInt cdof; /* The number of constraints on this point */ 4260 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4261 PetscScalar *a; 4262 PetscInt off, cind = 0, k; 4263 PetscErrorCode ierr; 4264 4265 PetscFunctionBegin; 4266 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4267 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4268 a = &array[off]; 4269 if (!cdof || setBC) { 4270 if (clperm) { 4271 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 4272 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 4273 } else { 4274 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 4275 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 4276 } 4277 } else { 4278 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4279 if (clperm) { 4280 if (perm) {for (k = 0; k < dof; ++k) { 4281 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4282 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 4283 } 4284 } else { 4285 for (k = 0; k < dof; ++k) { 4286 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4287 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 4288 } 4289 } 4290 } else { 4291 if (perm) { 4292 for (k = 0; k < dof; ++k) { 4293 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4294 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 4295 } 4296 } else { 4297 for (k = 0; k < dof; ++k) { 4298 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4299 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 4300 } 4301 } 4302 } 4303 } 4304 PetscFunctionReturn(0); 4305 } 4306 4307 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[]) 4308 { 4309 PetscInt cdof; /* The number of constraints on this point */ 4310 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4311 PetscScalar *a; 4312 PetscInt off, cind = 0, k; 4313 PetscErrorCode ierr; 4314 4315 PetscFunctionBegin; 4316 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4317 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4318 a = &array[off]; 4319 if (cdof) { 4320 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4321 if (clperm) { 4322 if (perm) { 4323 for (k = 0; k < dof; ++k) { 4324 if ((cind < cdof) && (k == cdofs[cind])) { 4325 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 4326 cind++; 4327 } 4328 } 4329 } else { 4330 for (k = 0; k < dof; ++k) { 4331 if ((cind < cdof) && (k == cdofs[cind])) { 4332 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 4333 cind++; 4334 } 4335 } 4336 } 4337 } else { 4338 if (perm) { 4339 for (k = 0; k < dof; ++k) { 4340 if ((cind < cdof) && (k == cdofs[cind])) { 4341 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 4342 cind++; 4343 } 4344 } 4345 } else { 4346 for (k = 0; k < dof; ++k) { 4347 if ((cind < cdof) && (k == cdofs[cind])) { 4348 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 4349 cind++; 4350 } 4351 } 4352 } 4353 } 4354 } 4355 PetscFunctionReturn(0); 4356 } 4357 4358 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[]) 4359 { 4360 PetscScalar *a; 4361 PetscInt fdof, foff, fcdof, foffset = *offset; 4362 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4363 PetscInt cind = 0, b; 4364 PetscErrorCode ierr; 4365 4366 PetscFunctionBegin; 4367 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4368 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 4369 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4370 a = &array[foff]; 4371 if (!fcdof || setBC) { 4372 if (clperm) { 4373 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 4374 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 4375 } else { 4376 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 4377 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 4378 } 4379 } else { 4380 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4381 if (clperm) { 4382 if (perm) { 4383 for (b = 0; b < fdof; b++) { 4384 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4385 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 4386 } 4387 } else { 4388 for (b = 0; b < fdof; b++) { 4389 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4390 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 4391 } 4392 } 4393 } else { 4394 if (perm) { 4395 for (b = 0; b < fdof; b++) { 4396 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4397 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 4398 } 4399 } else { 4400 for (b = 0; b < fdof; b++) { 4401 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4402 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 4403 } 4404 } 4405 } 4406 } 4407 *offset += fdof; 4408 PetscFunctionReturn(0); 4409 } 4410 4411 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[]) 4412 { 4413 PetscScalar *a; 4414 PetscInt fdof, foff, fcdof, foffset = *offset; 4415 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4416 PetscInt cind = 0, ncind = 0, b; 4417 PetscBool ncSet, fcSet; 4418 PetscErrorCode ierr; 4419 4420 PetscFunctionBegin; 4421 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4422 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 4423 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4424 a = &array[foff]; 4425 if (fcdof) { 4426 /* We just override fcdof and fcdofs with Ncc and comps */ 4427 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4428 if (clperm) { 4429 if (perm) { 4430 if (comps) { 4431 for (b = 0; b < fdof; b++) { 4432 ncSet = fcSet = PETSC_FALSE; 4433 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4434 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4435 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 4436 } 4437 } else { 4438 for (b = 0; b < fdof; b++) { 4439 if ((cind < fcdof) && (b == fcdofs[cind])) { 4440 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 4441 ++cind; 4442 } 4443 } 4444 } 4445 } else { 4446 if (comps) { 4447 for (b = 0; b < fdof; b++) { 4448 ncSet = fcSet = PETSC_FALSE; 4449 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4450 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4451 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 4452 } 4453 } else { 4454 for (b = 0; b < fdof; b++) { 4455 if ((cind < fcdof) && (b == fcdofs[cind])) { 4456 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 4457 ++cind; 4458 } 4459 } 4460 } 4461 } 4462 } else { 4463 if (perm) { 4464 if (comps) { 4465 for (b = 0; b < fdof; b++) { 4466 ncSet = fcSet = PETSC_FALSE; 4467 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4468 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4469 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 4470 } 4471 } else { 4472 for (b = 0; b < fdof; b++) { 4473 if ((cind < fcdof) && (b == fcdofs[cind])) { 4474 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 4475 ++cind; 4476 } 4477 } 4478 } 4479 } else { 4480 if (comps) { 4481 for (b = 0; b < fdof; b++) { 4482 ncSet = fcSet = PETSC_FALSE; 4483 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4484 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4485 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 4486 } 4487 } else { 4488 for (b = 0; b < fdof; b++) { 4489 if ((cind < fcdof) && (b == fcdofs[cind])) { 4490 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 4491 ++cind; 4492 } 4493 } 4494 } 4495 } 4496 } 4497 } 4498 *offset += fdof; 4499 PetscFunctionReturn(0); 4500 } 4501 4502 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4503 { 4504 PetscScalar *array; 4505 const PetscInt *cone, *coneO; 4506 PetscInt pStart, pEnd, p, numPoints, off, dof; 4507 PetscErrorCode ierr; 4508 4509 PetscFunctionBeginHot; 4510 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4511 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 4512 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4513 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 4514 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4515 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 4516 const PetscInt cp = !p ? point : cone[p-1]; 4517 const PetscInt o = !p ? 0 : coneO[p-1]; 4518 4519 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 4520 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4521 /* ADD_VALUES */ 4522 { 4523 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4524 PetscScalar *a; 4525 PetscInt cdof, coff, cind = 0, k; 4526 4527 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 4528 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 4529 a = &array[coff]; 4530 if (!cdof) { 4531 if (o >= 0) { 4532 for (k = 0; k < dof; ++k) { 4533 a[k] += values[off+k]; 4534 } 4535 } else { 4536 for (k = 0; k < dof; ++k) { 4537 a[k] += values[off+dof-k-1]; 4538 } 4539 } 4540 } else { 4541 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 4542 if (o >= 0) { 4543 for (k = 0; k < dof; ++k) { 4544 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4545 a[k] += values[off+k]; 4546 } 4547 } else { 4548 for (k = 0; k < dof; ++k) { 4549 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4550 a[k] += values[off+dof-k-1]; 4551 } 4552 } 4553 } 4554 } 4555 } 4556 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4557 PetscFunctionReturn(0); 4558 } 4559 4560 /*@C 4561 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 4562 4563 Not collective 4564 4565 Input Parameters: 4566 + dm - The DM 4567 . section - The section describing the layout in v, or NULL to use the default section 4568 . v - The local vector 4569 . point - The point in the DM 4570 . values - The array of values 4571 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 4572 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 4573 4574 Fortran Notes: 4575 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4576 4577 Level: intermediate 4578 4579 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 4580 @*/ 4581 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4582 { 4583 PetscSection clSection; 4584 IS clPoints; 4585 PetscScalar *array; 4586 PetscInt *points = NULL; 4587 const PetscInt *clp, *clperm; 4588 PetscInt depth, numFields, numPoints, p; 4589 PetscErrorCode ierr; 4590 4591 PetscFunctionBeginHot; 4592 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4593 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4594 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4595 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4596 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4597 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4598 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 4599 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 4600 PetscFunctionReturn(0); 4601 } 4602 /* Get points */ 4603 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 4604 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4605 /* Get array */ 4606 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4607 /* Get values */ 4608 if (numFields > 0) { 4609 PetscInt offset = 0, f; 4610 for (f = 0; f < numFields; ++f) { 4611 const PetscInt **perms = NULL; 4612 const PetscScalar **flips = NULL; 4613 4614 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4615 switch (mode) { 4616 case INSERT_VALUES: 4617 for (p = 0; p < numPoints; p++) { 4618 const PetscInt point = points[2*p]; 4619 const PetscInt *perm = perms ? perms[p] : NULL; 4620 const PetscScalar *flip = flips ? flips[p] : NULL; 4621 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 4622 } break; 4623 case INSERT_ALL_VALUES: 4624 for (p = 0; p < numPoints; p++) { 4625 const PetscInt point = points[2*p]; 4626 const PetscInt *perm = perms ? perms[p] : NULL; 4627 const PetscScalar *flip = flips ? flips[p] : NULL; 4628 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 4629 } break; 4630 case INSERT_BC_VALUES: 4631 for (p = 0; p < numPoints; p++) { 4632 const PetscInt point = points[2*p]; 4633 const PetscInt *perm = perms ? perms[p] : NULL; 4634 const PetscScalar *flip = flips ? flips[p] : NULL; 4635 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 4636 } break; 4637 case ADD_VALUES: 4638 for (p = 0; p < numPoints; p++) { 4639 const PetscInt point = points[2*p]; 4640 const PetscInt *perm = perms ? perms[p] : NULL; 4641 const PetscScalar *flip = flips ? flips[p] : NULL; 4642 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 4643 } break; 4644 case ADD_ALL_VALUES: 4645 for (p = 0; p < numPoints; p++) { 4646 const PetscInt point = points[2*p]; 4647 const PetscInt *perm = perms ? perms[p] : NULL; 4648 const PetscScalar *flip = flips ? flips[p] : NULL; 4649 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 4650 } break; 4651 case ADD_BC_VALUES: 4652 for (p = 0; p < numPoints; p++) { 4653 const PetscInt point = points[2*p]; 4654 const PetscInt *perm = perms ? perms[p] : NULL; 4655 const PetscScalar *flip = flips ? flips[p] : NULL; 4656 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 4657 } break; 4658 default: 4659 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4660 } 4661 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4662 } 4663 } else { 4664 PetscInt dof, off; 4665 const PetscInt **perms = NULL; 4666 const PetscScalar **flips = NULL; 4667 4668 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4669 switch (mode) { 4670 case INSERT_VALUES: 4671 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4672 const PetscInt point = points[2*p]; 4673 const PetscInt *perm = perms ? perms[p] : NULL; 4674 const PetscScalar *flip = flips ? flips[p] : NULL; 4675 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4676 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 4677 } break; 4678 case INSERT_ALL_VALUES: 4679 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4680 const PetscInt point = points[2*p]; 4681 const PetscInt *perm = perms ? perms[p] : NULL; 4682 const PetscScalar *flip = flips ? flips[p] : NULL; 4683 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4684 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 4685 } break; 4686 case INSERT_BC_VALUES: 4687 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4688 const PetscInt point = points[2*p]; 4689 const PetscInt *perm = perms ? perms[p] : NULL; 4690 const PetscScalar *flip = flips ? flips[p] : NULL; 4691 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4692 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 4693 } break; 4694 case ADD_VALUES: 4695 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4696 const PetscInt point = points[2*p]; 4697 const PetscInt *perm = perms ? perms[p] : NULL; 4698 const PetscScalar *flip = flips ? flips[p] : NULL; 4699 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4700 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 4701 } break; 4702 case ADD_ALL_VALUES: 4703 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4704 const PetscInt point = points[2*p]; 4705 const PetscInt *perm = perms ? perms[p] : NULL; 4706 const PetscScalar *flip = flips ? flips[p] : NULL; 4707 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4708 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 4709 } break; 4710 case ADD_BC_VALUES: 4711 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4712 const PetscInt point = points[2*p]; 4713 const PetscInt *perm = perms ? perms[p] : NULL; 4714 const PetscScalar *flip = flips ? flips[p] : NULL; 4715 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4716 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 4717 } break; 4718 default: 4719 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4720 } 4721 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4722 } 4723 /* Cleanup points */ 4724 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4725 /* Cleanup array */ 4726 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4727 PetscFunctionReturn(0); 4728 } 4729 4730 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, PetscInt Ncc, const PetscInt comps[], const PetscScalar values[], InsertMode mode) 4731 { 4732 PetscSection clSection; 4733 IS clPoints; 4734 PetscScalar *array; 4735 PetscInt *points = NULL; 4736 const PetscInt *clp, *clperm; 4737 PetscInt numFields, numPoints, p; 4738 PetscInt offset = 0, f; 4739 PetscErrorCode ierr; 4740 4741 PetscFunctionBeginHot; 4742 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4743 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4744 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4745 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4746 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4747 /* Get points */ 4748 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 4749 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4750 /* Get array */ 4751 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4752 /* Get values */ 4753 for (f = 0; f < numFields; ++f) { 4754 const PetscInt **perms = NULL; 4755 const PetscScalar **flips = NULL; 4756 4757 if (!fieldActive[f]) { 4758 for (p = 0; p < numPoints*2; p += 2) { 4759 PetscInt fdof; 4760 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4761 offset += fdof; 4762 } 4763 continue; 4764 } 4765 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4766 switch (mode) { 4767 case INSERT_VALUES: 4768 for (p = 0; p < numPoints; p++) { 4769 const PetscInt point = points[2*p]; 4770 const PetscInt *perm = perms ? perms[p] : NULL; 4771 const PetscScalar *flip = flips ? flips[p] : NULL; 4772 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 4773 } break; 4774 case INSERT_ALL_VALUES: 4775 for (p = 0; p < numPoints; p++) { 4776 const PetscInt point = points[2*p]; 4777 const PetscInt *perm = perms ? perms[p] : NULL; 4778 const PetscScalar *flip = flips ? flips[p] : NULL; 4779 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 4780 } break; 4781 case INSERT_BC_VALUES: 4782 for (p = 0; p < numPoints; p++) { 4783 const PetscInt point = points[2*p]; 4784 const PetscInt *perm = perms ? perms[p] : NULL; 4785 const PetscScalar *flip = flips ? flips[p] : NULL; 4786 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, clperm, values, &offset, array); 4787 } break; 4788 case ADD_VALUES: 4789 for (p = 0; p < numPoints; p++) { 4790 const PetscInt point = points[2*p]; 4791 const PetscInt *perm = perms ? perms[p] : NULL; 4792 const PetscScalar *flip = flips ? flips[p] : NULL; 4793 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 4794 } break; 4795 case ADD_ALL_VALUES: 4796 for (p = 0; p < numPoints; p++) { 4797 const PetscInt point = points[2*p]; 4798 const PetscInt *perm = perms ? perms[p] : NULL; 4799 const PetscScalar *flip = flips ? flips[p] : NULL; 4800 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 4801 } break; 4802 default: 4803 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4804 } 4805 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4806 } 4807 /* Cleanup points */ 4808 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4809 /* Cleanup array */ 4810 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4811 PetscFunctionReturn(0); 4812 } 4813 4814 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 4815 { 4816 PetscMPIInt rank; 4817 PetscInt i, j; 4818 PetscErrorCode ierr; 4819 4820 PetscFunctionBegin; 4821 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 4822 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 4823 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 4824 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 4825 numCIndices = numCIndices ? numCIndices : numRIndices; 4826 for (i = 0; i < numRIndices; i++) { 4827 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 4828 for (j = 0; j < numCIndices; j++) { 4829 #if defined(PETSC_USE_COMPLEX) 4830 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 4831 #else 4832 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 4833 #endif 4834 } 4835 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 4836 } 4837 PetscFunctionReturn(0); 4838 } 4839 4840 /* . off - The global offset of this point */ 4841 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], PetscInt indices[]) 4842 { 4843 PetscInt dof; /* The number of unknowns on this point */ 4844 PetscInt cdof; /* The number of constraints on this point */ 4845 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4846 PetscInt cind = 0, k; 4847 PetscErrorCode ierr; 4848 4849 PetscFunctionBegin; 4850 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4851 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4852 if (!cdof || setBC) { 4853 if (perm) { 4854 for (k = 0; k < dof; k++) indices[*loff+perm[k]] = off + k; 4855 } else { 4856 for (k = 0; k < dof; k++) indices[*loff+k] = off + k; 4857 } 4858 } else { 4859 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4860 if (perm) { 4861 for (k = 0; k < dof; ++k) { 4862 if ((cind < cdof) && (k == cdofs[cind])) { 4863 /* Insert check for returning constrained indices */ 4864 indices[*loff+perm[k]] = -(off+k+1); 4865 ++cind; 4866 } else { 4867 indices[*loff+perm[k]] = off+k-cind; 4868 } 4869 } 4870 } else { 4871 for (k = 0; k < dof; ++k) { 4872 if ((cind < cdof) && (k == cdofs[cind])) { 4873 /* Insert check for returning constrained indices */ 4874 indices[*loff+k] = -(off+k+1); 4875 ++cind; 4876 } else { 4877 indices[*loff+k] = off+k-cind; 4878 } 4879 } 4880 } 4881 } 4882 *loff += dof; 4883 PetscFunctionReturn(0); 4884 } 4885 4886 /* 4887 This version only believes the point offset from the globalSection 4888 4889 . off - The global offset of this point 4890 */ 4891 PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, PetscInt indices[]) 4892 { 4893 PetscInt numFields, foff, f; 4894 PetscErrorCode ierr; 4895 4896 PetscFunctionBegin; 4897 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4898 for (f = 0, foff = 0; f < numFields; ++f) { 4899 PetscInt fdof, cfdof; 4900 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4901 PetscInt cind = 0, b; 4902 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 4903 4904 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4905 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 4906 if (!cfdof || setBC) { 4907 if (perm) {for (b = 0; b < fdof; b++) {indices[foffs[f]+perm[b]] = off+foff+b;}} 4908 else {for (b = 0; b < fdof; b++) {indices[foffs[f]+ b ] = off+foff+b;}} 4909 } else { 4910 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4911 if (perm) { 4912 for (b = 0; b < fdof; b++) { 4913 if ((cind < cfdof) && (b == fcdofs[cind])) { 4914 indices[foffs[f]+perm[b]] = -(off+foff+b+1); 4915 ++cind; 4916 } else { 4917 indices[foffs[f]+perm[b]] = off+foff+b-cind; 4918 } 4919 } 4920 } else { 4921 for (b = 0; b < fdof; b++) { 4922 if ((cind < cfdof) && (b == fcdofs[cind])) { 4923 indices[foffs[f]+b] = -(off+foff+b+1); 4924 ++cind; 4925 } else { 4926 indices[foffs[f]+b] = off+foff+b-cind; 4927 } 4928 } 4929 } 4930 } 4931 foff += (setBC ? fdof : (fdof - cfdof)); 4932 foffs[f] += fdof; 4933 } 4934 PetscFunctionReturn(0); 4935 } 4936 4937 /* 4938 This version believes the globalSection offsets for each field, rather than just the point offset 4939 4940 . foffs - The offset into 'indices' for each field, since it is segregated by field 4941 */ 4942 PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, PetscInt indices[]) 4943 { 4944 PetscInt numFields, foff, f; 4945 PetscErrorCode ierr; 4946 4947 PetscFunctionBegin; 4948 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4949 for (f = 0; f < numFields; ++f) { 4950 PetscInt fdof, cfdof; 4951 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4952 PetscInt cind = 0, b; 4953 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 4954 4955 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4956 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 4957 ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 4958 if (!cfdof || setBC) { 4959 if (perm) {for (b = 0; b < fdof; b++) {indices[foffs[f]+perm[b]] = foff+b;}} 4960 else {for (b = 0; b < fdof; b++) {indices[foffs[f]+ b ] = foff+b;}} 4961 } else { 4962 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4963 if (perm) { 4964 for (b = 0; b < fdof; b++) { 4965 if ((cind < cfdof) && (b == fcdofs[cind])) { 4966 indices[foffs[f]+perm[b]] = -(foff+b+1); 4967 ++cind; 4968 } else { 4969 indices[foffs[f]+perm[b]] = foff+b-cind; 4970 } 4971 } 4972 } else { 4973 for (b = 0; b < fdof; b++) { 4974 if ((cind < cfdof) && (b == fcdofs[cind])) { 4975 indices[foffs[f]+b] = -(foff+b+1); 4976 ++cind; 4977 } else { 4978 indices[foffs[f]+b] = foff+b-cind; 4979 } 4980 } 4981 } 4982 } 4983 foffs[f] += fdof; 4984 } 4985 PetscFunctionReturn(0); 4986 } 4987 4988 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) 4989 { 4990 Mat cMat; 4991 PetscSection aSec, cSec; 4992 IS aIS; 4993 PetscInt aStart = -1, aEnd = -1; 4994 const PetscInt *anchors; 4995 PetscInt numFields, f, p, q, newP = 0; 4996 PetscInt newNumPoints = 0, newNumIndices = 0; 4997 PetscInt *newPoints, *indices, *newIndices; 4998 PetscInt maxAnchor, maxDof; 4999 PetscInt newOffsets[32]; 5000 PetscInt *pointMatOffsets[32]; 5001 PetscInt *newPointOffsets[32]; 5002 PetscScalar *pointMat[32]; 5003 PetscScalar *newValues=NULL,*tmpValues; 5004 PetscBool anyConstrained = PETSC_FALSE; 5005 PetscErrorCode ierr; 5006 5007 PetscFunctionBegin; 5008 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5009 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5010 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5011 5012 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 5013 /* if there are point-to-point constraints */ 5014 if (aSec) { 5015 ierr = PetscMemzero(newOffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5016 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 5017 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 5018 /* figure out how many points are going to be in the new element matrix 5019 * (we allow double counting, because it's all just going to be summed 5020 * into the global matrix anyway) */ 5021 for (p = 0; p < 2*numPoints; p+=2) { 5022 PetscInt b = points[p]; 5023 PetscInt bDof = 0, bSecDof; 5024 5025 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5026 if (!bSecDof) { 5027 continue; 5028 } 5029 if (b >= aStart && b < aEnd) { 5030 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 5031 } 5032 if (bDof) { 5033 /* this point is constrained */ 5034 /* it is going to be replaced by its anchors */ 5035 PetscInt bOff, q; 5036 5037 anyConstrained = PETSC_TRUE; 5038 newNumPoints += bDof; 5039 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 5040 for (q = 0; q < bDof; q++) { 5041 PetscInt a = anchors[bOff + q]; 5042 PetscInt aDof; 5043 5044 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 5045 newNumIndices += aDof; 5046 for (f = 0; f < numFields; ++f) { 5047 PetscInt fDof; 5048 5049 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 5050 newOffsets[f+1] += fDof; 5051 } 5052 } 5053 } 5054 else { 5055 /* this point is not constrained */ 5056 newNumPoints++; 5057 newNumIndices += bSecDof; 5058 for (f = 0; f < numFields; ++f) { 5059 PetscInt fDof; 5060 5061 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5062 newOffsets[f+1] += fDof; 5063 } 5064 } 5065 } 5066 } 5067 if (!anyConstrained) { 5068 if (outNumPoints) *outNumPoints = 0; 5069 if (outNumIndices) *outNumIndices = 0; 5070 if (outPoints) *outPoints = NULL; 5071 if (outValues) *outValues = NULL; 5072 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 5073 PetscFunctionReturn(0); 5074 } 5075 5076 if (outNumPoints) *outNumPoints = newNumPoints; 5077 if (outNumIndices) *outNumIndices = newNumIndices; 5078 5079 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 5080 5081 if (!outPoints && !outValues) { 5082 if (offsets) { 5083 for (f = 0; f <= numFields; f++) { 5084 offsets[f] = newOffsets[f]; 5085 } 5086 } 5087 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 5088 PetscFunctionReturn(0); 5089 } 5090 5091 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 5092 5093 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 5094 5095 /* workspaces */ 5096 if (numFields) { 5097 for (f = 0; f < numFields; f++) { 5098 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 5099 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 5100 } 5101 } 5102 else { 5103 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 5104 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 5105 } 5106 5107 /* get workspaces for the point-to-point matrices */ 5108 if (numFields) { 5109 PetscInt totalOffset, totalMatOffset; 5110 5111 for (p = 0; p < numPoints; p++) { 5112 PetscInt b = points[2*p]; 5113 PetscInt bDof = 0, bSecDof; 5114 5115 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5116 if (!bSecDof) { 5117 for (f = 0; f < numFields; f++) { 5118 newPointOffsets[f][p + 1] = 0; 5119 pointMatOffsets[f][p + 1] = 0; 5120 } 5121 continue; 5122 } 5123 if (b >= aStart && b < aEnd) { 5124 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5125 } 5126 if (bDof) { 5127 for (f = 0; f < numFields; f++) { 5128 PetscInt fDof, q, bOff, allFDof = 0; 5129 5130 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5131 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5132 for (q = 0; q < bDof; q++) { 5133 PetscInt a = anchors[bOff + q]; 5134 PetscInt aFDof; 5135 5136 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 5137 allFDof += aFDof; 5138 } 5139 newPointOffsets[f][p+1] = allFDof; 5140 pointMatOffsets[f][p+1] = fDof * allFDof; 5141 } 5142 } 5143 else { 5144 for (f = 0; f < numFields; f++) { 5145 PetscInt fDof; 5146 5147 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5148 newPointOffsets[f][p+1] = fDof; 5149 pointMatOffsets[f][p+1] = 0; 5150 } 5151 } 5152 } 5153 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 5154 newPointOffsets[f][0] = totalOffset; 5155 pointMatOffsets[f][0] = totalMatOffset; 5156 for (p = 0; p < numPoints; p++) { 5157 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 5158 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 5159 } 5160 totalOffset = newPointOffsets[f][numPoints]; 5161 totalMatOffset = pointMatOffsets[f][numPoints]; 5162 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 5163 } 5164 } 5165 else { 5166 for (p = 0; p < numPoints; p++) { 5167 PetscInt b = points[2*p]; 5168 PetscInt bDof = 0, bSecDof; 5169 5170 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5171 if (!bSecDof) { 5172 newPointOffsets[0][p + 1] = 0; 5173 pointMatOffsets[0][p + 1] = 0; 5174 continue; 5175 } 5176 if (b >= aStart && b < aEnd) { 5177 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5178 } 5179 if (bDof) { 5180 PetscInt bOff, q, allDof = 0; 5181 5182 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5183 for (q = 0; q < bDof; q++) { 5184 PetscInt a = anchors[bOff + q], aDof; 5185 5186 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 5187 allDof += aDof; 5188 } 5189 newPointOffsets[0][p+1] = allDof; 5190 pointMatOffsets[0][p+1] = bSecDof * allDof; 5191 } 5192 else { 5193 newPointOffsets[0][p+1] = bSecDof; 5194 pointMatOffsets[0][p+1] = 0; 5195 } 5196 } 5197 newPointOffsets[0][0] = 0; 5198 pointMatOffsets[0][0] = 0; 5199 for (p = 0; p < numPoints; p++) { 5200 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 5201 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 5202 } 5203 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 5204 } 5205 5206 /* output arrays */ 5207 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5208 5209 /* get the point-to-point matrices; construct newPoints */ 5210 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 5211 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 5212 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 5213 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 5214 if (numFields) { 5215 for (p = 0, newP = 0; p < numPoints; p++) { 5216 PetscInt b = points[2*p]; 5217 PetscInt o = points[2*p+1]; 5218 PetscInt bDof = 0, bSecDof; 5219 5220 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 5221 if (!bSecDof) { 5222 continue; 5223 } 5224 if (b >= aStart && b < aEnd) { 5225 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5226 } 5227 if (bDof) { 5228 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 5229 5230 fStart[0] = 0; 5231 fEnd[0] = 0; 5232 for (f = 0; f < numFields; f++) { 5233 PetscInt fDof; 5234 5235 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 5236 fStart[f+1] = fStart[f] + fDof; 5237 fEnd[f+1] = fStart[f+1]; 5238 } 5239 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 5240 ierr = DMPlexGetIndicesPointFields_Internal(cSec, b, bOff, fEnd, PETSC_TRUE, perms, p, indices);CHKERRQ(ierr); 5241 5242 fAnchorStart[0] = 0; 5243 fAnchorEnd[0] = 0; 5244 for (f = 0; f < numFields; f++) { 5245 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 5246 5247 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 5248 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 5249 } 5250 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5251 for (q = 0; q < bDof; q++) { 5252 PetscInt a = anchors[bOff + q], aOff; 5253 5254 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 5255 newPoints[2*(newP + q)] = a; 5256 newPoints[2*(newP + q) + 1] = 0; 5257 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 5258 ierr = DMPlexGetIndicesPointFields_Internal(section, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, newIndices);CHKERRQ(ierr); 5259 } 5260 newP += bDof; 5261 5262 if (outValues) { 5263 /* get the point-to-point submatrix */ 5264 for (f = 0; f < numFields; f++) { 5265 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 5266 } 5267 } 5268 } 5269 else { 5270 newPoints[2 * newP] = b; 5271 newPoints[2 * newP + 1] = o; 5272 newP++; 5273 } 5274 } 5275 } else { 5276 for (p = 0; p < numPoints; p++) { 5277 PetscInt b = points[2*p]; 5278 PetscInt o = points[2*p+1]; 5279 PetscInt bDof = 0, bSecDof; 5280 5281 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 5282 if (!bSecDof) { 5283 continue; 5284 } 5285 if (b >= aStart && b < aEnd) { 5286 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5287 } 5288 if (bDof) { 5289 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 5290 5291 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 5292 ierr = DMPlexGetIndicesPoint_Internal(cSec, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, indices);CHKERRQ(ierr); 5293 5294 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 5295 for (q = 0; q < bDof; q++) { 5296 PetscInt a = anchors[bOff + q], aOff; 5297 5298 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 5299 5300 newPoints[2*(newP + q)] = a; 5301 newPoints[2*(newP + q) + 1] = 0; 5302 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 5303 ierr = DMPlexGetIndicesPoint_Internal(section, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, newIndices);CHKERRQ(ierr); 5304 } 5305 newP += bDof; 5306 5307 /* get the point-to-point submatrix */ 5308 if (outValues) { 5309 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 5310 } 5311 } 5312 else { 5313 newPoints[2 * newP] = b; 5314 newPoints[2 * newP + 1] = o; 5315 newP++; 5316 } 5317 } 5318 } 5319 5320 if (outValues) { 5321 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 5322 ierr = PetscMemzero(tmpValues,newNumIndices*numIndices*sizeof(*tmpValues));CHKERRQ(ierr); 5323 /* multiply constraints on the right */ 5324 if (numFields) { 5325 for (f = 0; f < numFields; f++) { 5326 PetscInt oldOff = offsets[f]; 5327 5328 for (p = 0; p < numPoints; p++) { 5329 PetscInt cStart = newPointOffsets[f][p]; 5330 PetscInt b = points[2 * p]; 5331 PetscInt c, r, k; 5332 PetscInt dof; 5333 5334 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 5335 if (!dof) { 5336 continue; 5337 } 5338 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 5339 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 5340 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 5341 5342 for (r = 0; r < numIndices; r++) { 5343 for (c = 0; c < nCols; c++) { 5344 for (k = 0; k < dof; k++) { 5345 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 5346 } 5347 } 5348 } 5349 } 5350 else { 5351 /* copy this column as is */ 5352 for (r = 0; r < numIndices; r++) { 5353 for (c = 0; c < dof; c++) { 5354 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 5355 } 5356 } 5357 } 5358 oldOff += dof; 5359 } 5360 } 5361 } 5362 else { 5363 PetscInt oldOff = 0; 5364 for (p = 0; p < numPoints; p++) { 5365 PetscInt cStart = newPointOffsets[0][p]; 5366 PetscInt b = points[2 * p]; 5367 PetscInt c, r, k; 5368 PetscInt dof; 5369 5370 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 5371 if (!dof) { 5372 continue; 5373 } 5374 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 5375 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 5376 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 5377 5378 for (r = 0; r < numIndices; r++) { 5379 for (c = 0; c < nCols; c++) { 5380 for (k = 0; k < dof; k++) { 5381 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 5382 } 5383 } 5384 } 5385 } 5386 else { 5387 /* copy this column as is */ 5388 for (r = 0; r < numIndices; r++) { 5389 for (c = 0; c < dof; c++) { 5390 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 5391 } 5392 } 5393 } 5394 oldOff += dof; 5395 } 5396 } 5397 5398 if (multiplyLeft) { 5399 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 5400 ierr = PetscMemzero(newValues,newNumIndices*newNumIndices*sizeof(*newValues));CHKERRQ(ierr); 5401 /* multiply constraints transpose on the left */ 5402 if (numFields) { 5403 for (f = 0; f < numFields; f++) { 5404 PetscInt oldOff = offsets[f]; 5405 5406 for (p = 0; p < numPoints; p++) { 5407 PetscInt rStart = newPointOffsets[f][p]; 5408 PetscInt b = points[2 * p]; 5409 PetscInt c, r, k; 5410 PetscInt dof; 5411 5412 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 5413 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 5414 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 5415 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 5416 5417 for (r = 0; r < nRows; r++) { 5418 for (c = 0; c < newNumIndices; c++) { 5419 for (k = 0; k < dof; k++) { 5420 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 5421 } 5422 } 5423 } 5424 } 5425 else { 5426 /* copy this row as is */ 5427 for (r = 0; r < dof; r++) { 5428 for (c = 0; c < newNumIndices; c++) { 5429 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 5430 } 5431 } 5432 } 5433 oldOff += dof; 5434 } 5435 } 5436 } 5437 else { 5438 PetscInt oldOff = 0; 5439 5440 for (p = 0; p < numPoints; p++) { 5441 PetscInt rStart = newPointOffsets[0][p]; 5442 PetscInt b = points[2 * p]; 5443 PetscInt c, r, k; 5444 PetscInt dof; 5445 5446 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 5447 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 5448 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 5449 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 5450 5451 for (r = 0; r < nRows; r++) { 5452 for (c = 0; c < newNumIndices; c++) { 5453 for (k = 0; k < dof; k++) { 5454 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 5455 } 5456 } 5457 } 5458 } 5459 else { 5460 /* copy this row as is */ 5461 for (r = 0; r < dof; r++) { 5462 for (c = 0; c < newNumIndices; c++) { 5463 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 5464 } 5465 } 5466 } 5467 oldOff += dof; 5468 } 5469 } 5470 5471 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 5472 } 5473 else { 5474 newValues = tmpValues; 5475 } 5476 } 5477 5478 /* clean up */ 5479 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 5480 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 5481 5482 if (numFields) { 5483 for (f = 0; f < numFields; f++) { 5484 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 5485 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 5486 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 5487 } 5488 } 5489 else { 5490 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 5491 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 5492 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 5493 } 5494 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 5495 5496 /* output */ 5497 if (outPoints) { 5498 *outPoints = newPoints; 5499 } 5500 else { 5501 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5502 } 5503 if (outValues) { 5504 *outValues = newValues; 5505 } 5506 for (f = 0; f <= numFields; f++) { 5507 offsets[f] = newOffsets[f]; 5508 } 5509 PetscFunctionReturn(0); 5510 } 5511 5512 /*@C 5513 DMPlexGetClosureIndices - Get the global indices in a vector v for all points in the closure of the given point 5514 5515 Not collective 5516 5517 Input Parameters: 5518 + dm - The DM 5519 . section - The section describing the layout in v, or NULL to use the default section 5520 . globalSection - The section describing the parallel layout in v, or NULL to use the default section 5521 - point - The mesh point 5522 5523 Output parameters: 5524 + numIndices - The number of indices 5525 . indices - The indices 5526 - outOffsets - Field offset if not NULL 5527 5528 Note: Must call DMPlexRestoreClosureIndices() to free allocated memory 5529 5530 Level: advanced 5531 5532 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure() 5533 @*/ 5534 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices, PetscInt *outOffsets) 5535 { 5536 PetscSection clSection; 5537 IS clPoints; 5538 const PetscInt *clp; 5539 const PetscInt **perms[32] = {NULL}; 5540 PetscInt *points = NULL, *pointsNew; 5541 PetscInt numPoints, numPointsNew; 5542 PetscInt offsets[32]; 5543 PetscInt Nf, Nind, NindNew, off, globalOff, f, p; 5544 PetscErrorCode ierr; 5545 5546 PetscFunctionBegin; 5547 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5548 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5549 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 5550 if (numIndices) PetscValidPointer(numIndices, 4); 5551 PetscValidPointer(indices, 5); 5552 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5553 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 5554 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5555 /* Get points in closure */ 5556 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5557 /* Get number of indices and indices per field */ 5558 for (p = 0, Nind = 0; p < numPoints*2; p += 2) { 5559 PetscInt dof, fdof; 5560 5561 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5562 for (f = 0; f < Nf; ++f) { 5563 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5564 offsets[f+1] += fdof; 5565 } 5566 Nind += dof; 5567 } 5568 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 5569 if (Nf && offsets[Nf] != Nind) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Nind); 5570 if (!Nf) offsets[1] = Nind; 5571 /* Get dual space symmetries */ 5572 for (f = 0; f < PetscMax(1,Nf); f++) { 5573 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5574 else {ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5575 } 5576 /* Correct for hanging node constraints */ 5577 { 5578 ierr = DMPlexAnchorsModifyMat(dm, section, numPoints, Nind, points, perms, NULL, &numPointsNew, &NindNew, &pointsNew, NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 5579 if (numPointsNew) { 5580 for (f = 0; f < PetscMax(1,Nf); f++) { 5581 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5582 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5583 } 5584 for (f = 0; f < PetscMax(1,Nf); f++) { 5585 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section,f,numPointsNew,pointsNew,&perms[f],NULL);CHKERRQ(ierr);} 5586 else {ierr = PetscSectionGetPointSyms(section,numPointsNew,pointsNew,&perms[f],NULL);CHKERRQ(ierr);} 5587 } 5588 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5589 numPoints = numPointsNew; 5590 Nind = NindNew; 5591 points = pointsNew; 5592 } 5593 } 5594 /* Calculate indices */ 5595 ierr = DMGetWorkArray(dm, Nind, MPIU_INT, indices);CHKERRQ(ierr); 5596 if (Nf) { 5597 if (outOffsets) { 5598 PetscInt f; 5599 5600 for (f = 0; f <= Nf; f++) { 5601 outOffsets[f] = offsets[f]; 5602 } 5603 } 5604 for (p = 0; p < numPoints; p++) { 5605 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5606 DMPlexGetIndicesPointFields_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, perms, p, *indices); 5607 } 5608 } else { 5609 for (p = 0, off = 0; p < numPoints; p++) { 5610 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 5611 5612 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5613 DMPlexGetIndicesPoint_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, *indices); 5614 } 5615 } 5616 /* Cleanup points */ 5617 for (f = 0; f < PetscMax(1,Nf); f++) { 5618 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5619 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5620 } 5621 if (numPointsNew) { 5622 ierr = DMRestoreWorkArray(dm, 2*numPointsNew, MPIU_INT, &pointsNew);CHKERRQ(ierr); 5623 } else { 5624 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5625 } 5626 if (numIndices) *numIndices = Nind; 5627 PetscFunctionReturn(0); 5628 } 5629 5630 /*@C 5631 DMPlexRestoreClosureIndices - Restore the indices in a vector v for all points in the closure of the given point 5632 5633 Not collective 5634 5635 Input Parameters: 5636 + dm - The DM 5637 . section - The section describing the layout in v, or NULL to use the default section 5638 . globalSection - The section describing the parallel layout in v, or NULL to use the default section 5639 . point - The mesh point 5640 . numIndices - The number of indices 5641 . indices - The indices 5642 - outOffsets - Field offset if not NULL 5643 5644 Level: advanced 5645 5646 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure() 5647 @*/ 5648 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices,PetscInt *outOffsets) 5649 { 5650 PetscErrorCode ierr; 5651 5652 PetscFunctionBegin; 5653 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5654 PetscValidPointer(indices, 5); 5655 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 5656 PetscFunctionReturn(0); 5657 } 5658 5659 /*@C 5660 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 5661 5662 Not collective 5663 5664 Input Parameters: 5665 + dm - The DM 5666 . section - The section describing the layout in v, or NULL to use the default section 5667 . globalSection - The section describing the layout in v, or NULL to use the default global section 5668 . A - The matrix 5669 . point - The point in the DM 5670 . values - The array of values 5671 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 5672 5673 Fortran Notes: 5674 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 5675 5676 Level: intermediate 5677 5678 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 5679 @*/ 5680 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5681 { 5682 DM_Plex *mesh = (DM_Plex*) dm->data; 5683 PetscSection clSection; 5684 IS clPoints; 5685 PetscInt *points = NULL, *newPoints; 5686 const PetscInt *clp; 5687 PetscInt *indices; 5688 PetscInt offsets[32]; 5689 const PetscInt **perms[32] = {NULL}; 5690 const PetscScalar **flips[32] = {NULL}; 5691 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, p, f; 5692 PetscScalar *valCopy = NULL; 5693 PetscScalar *newValues; 5694 PetscErrorCode ierr; 5695 5696 PetscFunctionBegin; 5697 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5698 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 5699 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5700 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 5701 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 5702 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 5703 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5704 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5705 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5706 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5707 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 5708 PetscInt fdof; 5709 5710 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5711 for (f = 0; f < numFields; ++f) { 5712 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5713 offsets[f+1] += fdof; 5714 } 5715 numIndices += dof; 5716 } 5717 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 5718 5719 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[numFields], numIndices); 5720 /* Get symmetries */ 5721 for (f = 0; f < PetscMax(1,numFields); f++) { 5722 if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5723 else {ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5724 if (values && flips[f]) { /* may need to apply sign changes to the element matrix */ 5725 PetscInt foffset = offsets[f]; 5726 5727 for (p = 0; p < numPoints; p++) { 5728 PetscInt point = points[2*p], fdof; 5729 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 5730 5731 if (!numFields) { 5732 ierr = PetscSectionGetDof(section,point,&fdof);CHKERRQ(ierr); 5733 } else { 5734 ierr = PetscSectionGetFieldDof(section,point,f,&fdof);CHKERRQ(ierr); 5735 } 5736 if (flip) { 5737 PetscInt i, j, k; 5738 5739 if (!valCopy) { 5740 ierr = DMGetWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 5741 for (j = 0; j < numIndices * numIndices; j++) valCopy[j] = values[j]; 5742 values = valCopy; 5743 } 5744 for (i = 0; i < fdof; i++) { 5745 PetscScalar fval = flip[i]; 5746 5747 for (k = 0; k < numIndices; k++) { 5748 valCopy[numIndices * (foffset + i) + k] *= fval; 5749 valCopy[numIndices * k + (foffset + i)] *= fval; 5750 } 5751 } 5752 } 5753 foffset += fdof; 5754 } 5755 } 5756 } 5757 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,perms,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets,PETSC_TRUE);CHKERRQ(ierr); 5758 if (newNumPoints) { 5759 if (valCopy) { 5760 ierr = DMRestoreWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 5761 } 5762 for (f = 0; f < PetscMax(1,numFields); f++) { 5763 if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5764 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5765 } 5766 for (f = 0; f < PetscMax(1,numFields); f++) { 5767 if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,newNumPoints,newPoints,&perms[f],&flips[f]);CHKERRQ(ierr);} 5768 else {ierr = PetscSectionGetPointSyms(section,newNumPoints,newPoints,&perms[f],&flips[f]);CHKERRQ(ierr);} 5769 } 5770 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5771 numPoints = newNumPoints; 5772 numIndices = newNumIndices; 5773 points = newPoints; 5774 values = newValues; 5775 } 5776 ierr = DMGetWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr); 5777 if (numFields) { 5778 PetscBool useFieldOffsets; 5779 5780 ierr = PetscSectionGetUseFieldOffsets(globalSection, &useFieldOffsets);CHKERRQ(ierr); 5781 if (useFieldOffsets) { 5782 for (p = 0; p < numPoints; p++) { 5783 DMPlexGetIndicesPointFieldsSplit_Internal(section, globalSection, points[2*p], offsets, PETSC_FALSE, perms, p, indices); 5784 } 5785 } else { 5786 for (p = 0; p < numPoints; p++) { 5787 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5788 DMPlexGetIndicesPointFields_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, perms, p, indices); 5789 } 5790 } 5791 } else { 5792 for (p = 0, off = 0; p < numPoints; p++) { 5793 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 5794 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5795 DMPlexGetIndicesPoint_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, indices); 5796 } 5797 } 5798 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 5799 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 5800 if (mesh->printFEM > 1) { 5801 PetscInt i; 5802 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 5803 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 5804 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5805 } 5806 if (ierr) { 5807 PetscMPIInt rank; 5808 PetscErrorCode ierr2; 5809 5810 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5811 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5812 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 5813 ierr2 = DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr2); 5814 CHKERRQ(ierr); 5815 } 5816 for (f = 0; f < PetscMax(1,numFields); f++) { 5817 if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5818 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5819 } 5820 if (newNumPoints) { 5821 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 5822 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5823 } 5824 else { 5825 if (valCopy) { 5826 ierr = DMRestoreWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 5827 } 5828 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5829 } 5830 ierr = DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr); 5831 PetscFunctionReturn(0); 5832 } 5833 5834 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5835 { 5836 DM_Plex *mesh = (DM_Plex*) dmf->data; 5837 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5838 PetscInt *cpoints = NULL; 5839 PetscInt *findices, *cindices; 5840 PetscInt foffsets[32], coffsets[32]; 5841 CellRefiner cellRefiner; 5842 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5843 PetscErrorCode ierr; 5844 5845 PetscFunctionBegin; 5846 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5847 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5848 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 5849 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5850 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 5851 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5852 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5853 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5854 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5855 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5856 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 5857 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5858 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5859 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5860 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5861 /* Column indices */ 5862 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5863 maxFPoints = numCPoints; 5864 /* Compress out points not in the section */ 5865 /* TODO: Squeeze out points with 0 dof as well */ 5866 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5867 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5868 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5869 cpoints[q*2] = cpoints[p]; 5870 cpoints[q*2+1] = cpoints[p+1]; 5871 ++q; 5872 } 5873 } 5874 numCPoints = q; 5875 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5876 PetscInt fdof; 5877 5878 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5879 if (!dof) continue; 5880 for (f = 0; f < numFields; ++f) { 5881 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5882 coffsets[f+1] += fdof; 5883 } 5884 numCIndices += dof; 5885 } 5886 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5887 /* Row indices */ 5888 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5889 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5890 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 5891 for (r = 0, q = 0; r < numSubcells; ++r) { 5892 /* TODO Map from coarse to fine cells */ 5893 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5894 /* Compress out points not in the section */ 5895 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5896 for (p = 0; p < numFPoints*2; p += 2) { 5897 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5898 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5899 if (!dof) continue; 5900 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5901 if (s < q) continue; 5902 ftotpoints[q*2] = fpoints[p]; 5903 ftotpoints[q*2+1] = fpoints[p+1]; 5904 ++q; 5905 } 5906 } 5907 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5908 } 5909 numFPoints = q; 5910 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5911 PetscInt fdof; 5912 5913 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5914 if (!dof) continue; 5915 for (f = 0; f < numFields; ++f) { 5916 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5917 foffsets[f+1] += fdof; 5918 } 5919 numFIndices += dof; 5920 } 5921 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5922 5923 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 5924 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 5925 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 5926 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 5927 if (numFields) { 5928 const PetscInt **permsF[32] = {NULL}; 5929 const PetscInt **permsC[32] = {NULL}; 5930 5931 for (f = 0; f < numFields; f++) { 5932 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 5933 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 5934 } 5935 for (p = 0; p < numFPoints; p++) { 5936 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 5937 DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, findices); 5938 } 5939 for (p = 0; p < numCPoints; p++) { 5940 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 5941 DMPlexGetIndicesPointFields_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cindices); 5942 } 5943 for (f = 0; f < numFields; f++) { 5944 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 5945 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 5946 } 5947 } else { 5948 const PetscInt **permsF = NULL; 5949 const PetscInt **permsC = NULL; 5950 5951 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 5952 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 5953 for (p = 0, off = 0; p < numFPoints; p++) { 5954 const PetscInt *perm = permsF ? permsF[p] : NULL; 5955 5956 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 5957 ierr = DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, findices);CHKERRQ(ierr); 5958 } 5959 for (p = 0, off = 0; p < numCPoints; p++) { 5960 const PetscInt *perm = permsC ? permsC[p] : NULL; 5961 5962 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 5963 ierr = DMPlexGetIndicesPoint_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cindices);CHKERRQ(ierr); 5964 } 5965 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 5966 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 5967 } 5968 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 5969 /* TODO: flips */ 5970 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 5971 if (ierr) { 5972 PetscMPIInt rank; 5973 PetscErrorCode ierr2; 5974 5975 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5976 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5977 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 5978 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 5979 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 5980 CHKERRQ(ierr); 5981 } 5982 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 5983 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5984 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 5985 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 5986 PetscFunctionReturn(0); 5987 } 5988 5989 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 5990 { 5991 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5992 PetscInt *cpoints = NULL; 5993 PetscInt foffsets[32], coffsets[32]; 5994 CellRefiner cellRefiner; 5995 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5996 PetscErrorCode ierr; 5997 5998 PetscFunctionBegin; 5999 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 6000 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 6001 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 6002 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 6003 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 6004 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 6005 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 6006 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 6007 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 6008 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 6009 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 6010 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6011 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6012 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 6013 /* Column indices */ 6014 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 6015 maxFPoints = numCPoints; 6016 /* Compress out points not in the section */ 6017 /* TODO: Squeeze out points with 0 dof as well */ 6018 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 6019 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 6020 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 6021 cpoints[q*2] = cpoints[p]; 6022 cpoints[q*2+1] = cpoints[p+1]; 6023 ++q; 6024 } 6025 } 6026 numCPoints = q; 6027 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 6028 PetscInt fdof; 6029 6030 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 6031 if (!dof) continue; 6032 for (f = 0; f < numFields; ++f) { 6033 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 6034 coffsets[f+1] += fdof; 6035 } 6036 numCIndices += dof; 6037 } 6038 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 6039 /* Row indices */ 6040 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 6041 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 6042 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6043 for (r = 0, q = 0; r < numSubcells; ++r) { 6044 /* TODO Map from coarse to fine cells */ 6045 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6046 /* Compress out points not in the section */ 6047 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 6048 for (p = 0; p < numFPoints*2; p += 2) { 6049 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 6050 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 6051 if (!dof) continue; 6052 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 6053 if (s < q) continue; 6054 ftotpoints[q*2] = fpoints[p]; 6055 ftotpoints[q*2+1] = fpoints[p+1]; 6056 ++q; 6057 } 6058 } 6059 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6060 } 6061 numFPoints = q; 6062 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 6063 PetscInt fdof; 6064 6065 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 6066 if (!dof) continue; 6067 for (f = 0; f < numFields; ++f) { 6068 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 6069 foffsets[f+1] += fdof; 6070 } 6071 numFIndices += dof; 6072 } 6073 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 6074 6075 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 6076 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 6077 if (numFields) { 6078 const PetscInt **permsF[32] = {NULL}; 6079 const PetscInt **permsC[32] = {NULL}; 6080 6081 for (f = 0; f < numFields; f++) { 6082 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 6083 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6084 } 6085 for (p = 0; p < numFPoints; p++) { 6086 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6087 DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, findices); 6088 } 6089 for (p = 0; p < numCPoints; p++) { 6090 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 6091 DMPlexGetIndicesPointFields_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cindices); 6092 } 6093 for (f = 0; f < numFields; f++) { 6094 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 6095 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6096 } 6097 } else { 6098 const PetscInt **permsF = NULL; 6099 const PetscInt **permsC = NULL; 6100 6101 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 6102 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6103 for (p = 0, off = 0; p < numFPoints; p++) { 6104 const PetscInt *perm = permsF ? permsF[p] : NULL; 6105 6106 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 6107 DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, findices); 6108 } 6109 for (p = 0, off = 0; p < numCPoints; p++) { 6110 const PetscInt *perm = permsC ? permsC[p] : NULL; 6111 6112 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 6113 DMPlexGetIndicesPoint_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cindices); 6114 } 6115 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 6116 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6117 } 6118 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6119 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 6120 PetscFunctionReturn(0); 6121 } 6122 6123 /*@ 6124 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 6125 6126 Input Parameter: 6127 . dm - The DMPlex object 6128 6129 Output Parameters: 6130 + cMax - The first hybrid cell 6131 . fMax - The first hybrid face 6132 . eMax - The first hybrid edge 6133 - vMax - The first hybrid vertex 6134 6135 Level: developer 6136 6137 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 6138 @*/ 6139 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 6140 { 6141 DM_Plex *mesh = (DM_Plex*) dm->data; 6142 PetscInt dim; 6143 PetscErrorCode ierr; 6144 6145 PetscFunctionBegin; 6146 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6147 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6148 if (cMax) *cMax = mesh->hybridPointMax[dim]; 6149 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 6150 if (eMax) *eMax = mesh->hybridPointMax[1]; 6151 if (vMax) *vMax = mesh->hybridPointMax[0]; 6152 PetscFunctionReturn(0); 6153 } 6154 6155 /*@ 6156 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 6157 6158 Input Parameters: 6159 . dm - The DMPlex object 6160 . cMax - The first hybrid cell 6161 . fMax - The first hybrid face 6162 . eMax - The first hybrid edge 6163 - vMax - The first hybrid vertex 6164 6165 Level: developer 6166 6167 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 6168 @*/ 6169 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 6170 { 6171 DM_Plex *mesh = (DM_Plex*) dm->data; 6172 PetscInt dim; 6173 PetscErrorCode ierr; 6174 6175 PetscFunctionBegin; 6176 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6177 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6178 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 6179 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 6180 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 6181 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 6182 PetscFunctionReturn(0); 6183 } 6184 6185 /*@C 6186 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 6187 6188 Input Parameter: 6189 . dm - The DMPlex object 6190 6191 Output Parameter: 6192 . cellHeight - The height of a cell 6193 6194 Level: developer 6195 6196 .seealso DMPlexSetVTKCellHeight() 6197 @*/ 6198 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 6199 { 6200 DM_Plex *mesh = (DM_Plex*) dm->data; 6201 6202 PetscFunctionBegin; 6203 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6204 PetscValidPointer(cellHeight, 2); 6205 *cellHeight = mesh->vtkCellHeight; 6206 PetscFunctionReturn(0); 6207 } 6208 6209 /*@C 6210 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 6211 6212 Input Parameters: 6213 + dm - The DMPlex object 6214 - cellHeight - The height of a cell 6215 6216 Level: developer 6217 6218 .seealso DMPlexGetVTKCellHeight() 6219 @*/ 6220 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 6221 { 6222 DM_Plex *mesh = (DM_Plex*) dm->data; 6223 6224 PetscFunctionBegin; 6225 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6226 mesh->vtkCellHeight = cellHeight; 6227 PetscFunctionReturn(0); 6228 } 6229 6230 /* We can easily have a form that takes an IS instead */ 6231 static PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 6232 { 6233 PetscSection section, globalSection; 6234 PetscInt *numbers, p; 6235 PetscErrorCode ierr; 6236 6237 PetscFunctionBegin; 6238 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 6239 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 6240 for (p = pStart; p < pEnd; ++p) { 6241 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 6242 } 6243 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 6244 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 6245 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 6246 for (p = pStart; p < pEnd; ++p) { 6247 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 6248 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 6249 else numbers[p-pStart] += shift; 6250 } 6251 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 6252 if (globalSize) { 6253 PetscLayout layout; 6254 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 6255 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 6256 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 6257 } 6258 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6259 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 6260 PetscFunctionReturn(0); 6261 } 6262 6263 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 6264 { 6265 PetscInt cellHeight, cStart, cEnd, cMax; 6266 PetscErrorCode ierr; 6267 6268 PetscFunctionBegin; 6269 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 6270 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 6271 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 6272 if (cMax >= 0 && !includeHybrid) cEnd = PetscMin(cEnd, cMax); 6273 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 6274 PetscFunctionReturn(0); 6275 } 6276 6277 /*@C 6278 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 6279 6280 Input Parameter: 6281 . dm - The DMPlex object 6282 6283 Output Parameter: 6284 . globalCellNumbers - Global cell numbers for all cells on this process 6285 6286 Level: developer 6287 6288 .seealso DMPlexGetVertexNumbering() 6289 @*/ 6290 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 6291 { 6292 DM_Plex *mesh = (DM_Plex*) dm->data; 6293 PetscErrorCode ierr; 6294 6295 PetscFunctionBegin; 6296 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6297 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 6298 *globalCellNumbers = mesh->globalCellNumbers; 6299 PetscFunctionReturn(0); 6300 } 6301 6302 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 6303 { 6304 PetscInt vStart, vEnd, vMax; 6305 PetscErrorCode ierr; 6306 6307 PetscFunctionBegin; 6308 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6309 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6310 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 6311 if (vMax >= 0 && !includeHybrid) vEnd = PetscMin(vEnd, vMax); 6312 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 6313 PetscFunctionReturn(0); 6314 } 6315 6316 /*@C 6317 DMPlexGetVertexNumbering - Get a global certex numbering for all vertices on this process 6318 6319 Input Parameter: 6320 . dm - The DMPlex object 6321 6322 Output Parameter: 6323 . globalVertexNumbers - Global vertex numbers for all vertices on this process 6324 6325 Level: developer 6326 6327 .seealso DMPlexGetCellNumbering() 6328 @*/ 6329 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 6330 { 6331 DM_Plex *mesh = (DM_Plex*) dm->data; 6332 PetscErrorCode ierr; 6333 6334 PetscFunctionBegin; 6335 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6336 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 6337 *globalVertexNumbers = mesh->globalVertexNumbers; 6338 PetscFunctionReturn(0); 6339 } 6340 6341 /*@C 6342 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 6343 6344 Input Parameter: 6345 . dm - The DMPlex object 6346 6347 Output Parameter: 6348 . globalPointNumbers - Global numbers for all points on this process 6349 6350 Level: developer 6351 6352 .seealso DMPlexGetCellNumbering() 6353 @*/ 6354 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 6355 { 6356 IS nums[4]; 6357 PetscInt depths[4]; 6358 PetscInt depth, d, shift = 0; 6359 PetscErrorCode ierr; 6360 6361 PetscFunctionBegin; 6362 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6363 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6364 /* For unstratified meshes use dim instead of depth */ 6365 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 6366 depths[0] = depth; depths[1] = 0; 6367 for (d = 2; d <= depth; ++d) depths[d] = depth-d+1; 6368 for (d = 0; d <= depth; ++d) { 6369 PetscInt pStart, pEnd, gsize; 6370 6371 ierr = DMPlexGetDepthStratum(dm, depths[d], &pStart, &pEnd);CHKERRQ(ierr); 6372 ierr = DMPlexCreateNumbering_Private(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 6373 shift += gsize; 6374 } 6375 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 6376 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 6377 PetscFunctionReturn(0); 6378 } 6379 6380 6381 /*@ 6382 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 6383 6384 Input Parameter: 6385 . dm - The DMPlex object 6386 6387 Output Parameter: 6388 . ranks - The rank field 6389 6390 Options Database Keys: 6391 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 6392 6393 Level: intermediate 6394 6395 .seealso: DMView() 6396 @*/ 6397 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 6398 { 6399 DM rdm; 6400 PetscDS prob; 6401 PetscFE fe; 6402 PetscScalar *r; 6403 PetscMPIInt rank; 6404 PetscInt dim, cStart, cEnd, c; 6405 PetscErrorCode ierr; 6406 6407 PetscFunctionBeginUser; 6408 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 6409 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 6410 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 6411 ierr = PetscFECreateDefault(rdm, dim, 1, PETSC_TRUE, NULL, -1, &fe);CHKERRQ(ierr); 6412 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 6413 ierr = DMGetDS(rdm, &prob);CHKERRQ(ierr); 6414 ierr = PetscDSSetDiscretization(prob, 0, (PetscObject) fe);CHKERRQ(ierr); 6415 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 6416 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6417 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 6418 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 6419 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 6420 for (c = cStart; c < cEnd; ++c) { 6421 PetscScalar *lr; 6422 6423 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 6424 *lr = rank; 6425 } 6426 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 6427 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 6428 PetscFunctionReturn(0); 6429 } 6430 6431 /*@ 6432 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 6433 6434 Input Parameter: 6435 . dm - The DMPlex object 6436 6437 Note: This is a useful diagnostic when creating meshes programmatically. 6438 6439 Level: developer 6440 6441 .seealso: DMCreate(), DMCheckSkeleton(), DMCheckFaces() 6442 @*/ 6443 PetscErrorCode DMPlexCheckSymmetry(DM dm) 6444 { 6445 PetscSection coneSection, supportSection; 6446 const PetscInt *cone, *support; 6447 PetscInt coneSize, c, supportSize, s; 6448 PetscInt pStart, pEnd, p, csize, ssize; 6449 PetscErrorCode ierr; 6450 6451 PetscFunctionBegin; 6452 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6453 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 6454 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 6455 /* Check that point p is found in the support of its cone points, and vice versa */ 6456 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6457 for (p = pStart; p < pEnd; ++p) { 6458 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 6459 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 6460 for (c = 0; c < coneSize; ++c) { 6461 PetscBool dup = PETSC_FALSE; 6462 PetscInt d; 6463 for (d = c-1; d >= 0; --d) { 6464 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 6465 } 6466 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 6467 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 6468 for (s = 0; s < supportSize; ++s) { 6469 if (support[s] == p) break; 6470 } 6471 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 6472 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 6473 for (s = 0; s < coneSize; ++s) { 6474 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 6475 } 6476 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6477 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 6478 for (s = 0; s < supportSize; ++s) { 6479 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 6480 } 6481 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6482 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 6483 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 6484 } 6485 } 6486 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 6487 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 6488 for (s = 0; s < supportSize; ++s) { 6489 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6490 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6491 for (c = 0; c < coneSize; ++c) { 6492 if (cone[c] == p) break; 6493 } 6494 if (c >= coneSize) { 6495 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 6496 for (c = 0; c < supportSize; ++c) { 6497 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 6498 } 6499 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6500 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 6501 for (c = 0; c < coneSize; ++c) { 6502 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 6503 } 6504 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6505 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 6506 } 6507 } 6508 } 6509 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 6510 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 6511 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 6512 PetscFunctionReturn(0); 6513 } 6514 6515 /*@ 6516 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 6517 6518 Input Parameters: 6519 + dm - The DMPlex object 6520 . isSimplex - Are the cells simplices or tensor products 6521 - cellHeight - Normally 0 6522 6523 Note: This is a useful diagnostic when creating meshes programmatically. 6524 6525 Level: developer 6526 6527 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckFaces() 6528 @*/ 6529 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight) 6530 { 6531 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 6532 PetscErrorCode ierr; 6533 6534 PetscFunctionBegin; 6535 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6536 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6537 switch (dim) { 6538 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 6539 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 6540 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 6541 default: 6542 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %D", dim); 6543 } 6544 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6545 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 6546 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 6547 cMax = cMax >= 0 ? cMax : cEnd; 6548 for (c = cStart; c < cMax; ++c) { 6549 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 6550 6551 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6552 for (cl = 0; cl < closureSize*2; cl += 2) { 6553 const PetscInt p = closure[cl]; 6554 if ((p >= vStart) && (p < vEnd)) ++coneSize; 6555 } 6556 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6557 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has %D vertices != %D", c, coneSize, numCorners); 6558 } 6559 for (c = cMax; c < cEnd; ++c) { 6560 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 6561 6562 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6563 for (cl = 0; cl < closureSize*2; cl += 2) { 6564 const PetscInt p = closure[cl]; 6565 if ((p >= vStart) && (p < vEnd)) ++coneSize; 6566 } 6567 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6568 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %D has %D vertices > %D", c, coneSize, numHybridCorners); 6569 } 6570 PetscFunctionReturn(0); 6571 } 6572 6573 /*@ 6574 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 6575 6576 Input Parameters: 6577 + dm - The DMPlex object 6578 . isSimplex - Are the cells simplices or tensor products 6579 - cellHeight - Normally 0 6580 6581 Note: This is a useful diagnostic when creating meshes programmatically. 6582 6583 Level: developer 6584 6585 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton() 6586 @*/ 6587 PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight) 6588 { 6589 PetscInt pMax[4]; 6590 PetscInt dim, vStart, vEnd, cStart, cEnd, c, h; 6591 PetscErrorCode ierr; 6592 6593 PetscFunctionBegin; 6594 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6595 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6596 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6597 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 6598 for (h = cellHeight; h < dim; ++h) { 6599 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 6600 for (c = cStart; c < cEnd; ++c) { 6601 const PetscInt *cone, *ornt, *faces; 6602 PetscInt numFaces, faceSize, coneSize,f; 6603 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 6604 6605 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 6606 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 6607 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6608 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6609 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6610 for (cl = 0; cl < closureSize*2; cl += 2) { 6611 const PetscInt p = closure[cl]; 6612 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 6613 } 6614 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 6615 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has %D faces but should have %D", c, coneSize, numFaces); 6616 for (f = 0; f < numFaces; ++f) { 6617 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 6618 6619 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 6620 for (cl = 0; cl < fclosureSize*2; cl += 2) { 6621 const PetscInt p = fclosure[cl]; 6622 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 6623 } 6624 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); 6625 for (v = 0; v < fnumCorners; ++v) { 6626 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]); 6627 } 6628 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 6629 } 6630 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 6631 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6632 } 6633 } 6634 PetscFunctionReturn(0); 6635 } 6636 6637 /* Pointwise interpolation 6638 Just code FEM for now 6639 u^f = I u^c 6640 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 6641 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 6642 I_{ij} = psi^f_i phi^c_j 6643 */ 6644 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 6645 { 6646 PetscSection gsc, gsf; 6647 PetscInt m, n; 6648 void *ctx; 6649 DM cdm; 6650 PetscBool regular; 6651 PetscErrorCode ierr; 6652 6653 PetscFunctionBegin; 6654 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 6655 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 6656 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 6657 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 6658 6659 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 6660 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6661 ierr = MatSetType(*interpolation, dmCoarse->mattype);CHKERRQ(ierr); 6662 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 6663 6664 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 6665 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 6666 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 6667 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 6668 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 6669 /* Use naive scaling */ 6670 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 6671 PetscFunctionReturn(0); 6672 } 6673 6674 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 6675 { 6676 PetscErrorCode ierr; 6677 VecScatter ctx; 6678 6679 PetscFunctionBegin; 6680 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 6681 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 6682 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 6683 PetscFunctionReturn(0); 6684 } 6685 6686 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 6687 { 6688 PetscSection gsc, gsf; 6689 PetscInt m, n; 6690 void *ctx; 6691 DM cdm; 6692 PetscBool regular; 6693 PetscErrorCode ierr; 6694 6695 PetscFunctionBegin; 6696 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 6697 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 6698 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 6699 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 6700 6701 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 6702 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6703 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 6704 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 6705 6706 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 6707 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 6708 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 6709 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 6710 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 6711 PetscFunctionReturn(0); 6712 } 6713 6714 PetscErrorCode DMCreateDefaultSection_Plex(DM dm) 6715 { 6716 PetscSection section; 6717 IS *bcPoints, *bcComps; 6718 PetscBool *isFE; 6719 PetscInt *bcFields, *numComp, *numDof; 6720 PetscInt depth, dim, numBd, numBC = 0, numFields, bd, bc = 0, f; 6721 PetscInt cStart, cEnd, cEndInterior; 6722 PetscErrorCode ierr; 6723 6724 PetscFunctionBegin; 6725 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 6726 /* FE and FV boundary conditions are handled slightly differently */ 6727 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 6728 for (f = 0; f < numFields; ++f) { 6729 PetscObject obj; 6730 PetscClassId id; 6731 6732 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 6733 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 6734 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 6735 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 6736 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %D", f); 6737 } 6738 /* Allocate boundary point storage for FEM boundaries */ 6739 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6740 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6741 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6742 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 6743 ierr = PetscDSGetNumBoundary(dm->prob, &numBd);CHKERRQ(ierr); 6744 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)"); 6745 for (bd = 0; bd < numBd; ++bd) { 6746 PetscInt field; 6747 DMBoundaryConditionType type; 6748 const char *labelName; 6749 DMLabel label; 6750 6751 ierr = PetscDSGetBoundary(dm->prob, bd, &type, NULL, &labelName, &field, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 6752 ierr = DMGetLabel(dm,labelName,&label);CHKERRQ(ierr); 6753 if (label && isFE[field] && (type & DM_BC_ESSENTIAL)) ++numBC; 6754 } 6755 /* Add ghost cell boundaries for FVM */ 6756 for (f = 0; f < numFields; ++f) if (!isFE[f] && cEndInterior >= 0) ++numBC; 6757 ierr = PetscCalloc3(numBC,&bcFields,numBC,&bcPoints,numBC,&bcComps);CHKERRQ(ierr); 6758 /* Constrain ghost cells for FV */ 6759 for (f = 0; f < numFields; ++f) { 6760 PetscInt *newidx, c; 6761 6762 if (isFE[f] || cEndInterior < 0) continue; 6763 ierr = PetscMalloc1(cEnd-cEndInterior,&newidx);CHKERRQ(ierr); 6764 for (c = cEndInterior; c < cEnd; ++c) newidx[c-cEndInterior] = c; 6765 bcFields[bc] = f; 6766 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), cEnd-cEndInterior, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 6767 } 6768 /* Handle FEM Dirichlet boundaries */ 6769 for (bd = 0; bd < numBd; ++bd) { 6770 const char *bdLabel; 6771 DMLabel label; 6772 const PetscInt *comps; 6773 const PetscInt *values; 6774 PetscInt bd2, field, numComps, numValues; 6775 DMBoundaryConditionType type; 6776 PetscBool duplicate = PETSC_FALSE; 6777 6778 ierr = PetscDSGetBoundary(dm->prob, bd, &type, NULL, &bdLabel, &field, &numComps, &comps, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 6779 ierr = DMGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 6780 if (!isFE[field] || !label) continue; 6781 /* Only want to modify label once */ 6782 for (bd2 = 0; bd2 < bd; ++bd2) { 6783 const char *bdname; 6784 ierr = PetscDSGetBoundary(dm->prob, bd2, NULL, NULL, &bdname, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 6785 ierr = PetscStrcmp(bdname, bdLabel, &duplicate);CHKERRQ(ierr); 6786 if (duplicate) break; 6787 } 6788 if (!duplicate && (isFE[field])) { 6789 /* don't complete cells, which are just present to give orientation to the boundary */ 6790 ierr = DMPlexLabelComplete(dm, label);CHKERRQ(ierr); 6791 } 6792 /* Filter out cells, if you actually want to constrain cells you need to do things by hand right now */ 6793 if (type & DM_BC_ESSENTIAL) { 6794 PetscInt *newidx; 6795 PetscInt n, newn = 0, p, v; 6796 6797 bcFields[bc] = field; 6798 if (numComps) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), numComps, comps, PETSC_COPY_VALUES, &bcComps[bc]);CHKERRQ(ierr);} 6799 for (v = 0; v < numValues; ++v) { 6800 IS tmp; 6801 const PetscInt *idx; 6802 6803 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 6804 if (!tmp) continue; 6805 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 6806 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 6807 if (isFE[field]) { 6808 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) ++newn; 6809 } else { 6810 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) ++newn; 6811 } 6812 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 6813 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 6814 } 6815 ierr = PetscMalloc1(newn,&newidx);CHKERRQ(ierr); 6816 newn = 0; 6817 for (v = 0; v < numValues; ++v) { 6818 IS tmp; 6819 const PetscInt *idx; 6820 6821 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 6822 if (!tmp) continue; 6823 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 6824 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 6825 if (isFE[field]) { 6826 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) newidx[newn++] = idx[p]; 6827 } else { 6828 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) newidx[newn++] = idx[p]; 6829 } 6830 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 6831 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 6832 } 6833 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), newn, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 6834 } 6835 } 6836 /* Handle discretization */ 6837 ierr = PetscCalloc2(numFields,&numComp,numFields*(dim+1),&numDof);CHKERRQ(ierr); 6838 for (f = 0; f < numFields; ++f) { 6839 PetscObject obj; 6840 6841 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 6842 if (isFE[f]) { 6843 PetscFE fe = (PetscFE) obj; 6844 const PetscInt *numFieldDof; 6845 PetscInt d; 6846 6847 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 6848 ierr = PetscFEGetNumDof(fe, &numFieldDof);CHKERRQ(ierr); 6849 for (d = 0; d < dim+1; ++d) numDof[f*(dim+1)+d] = numFieldDof[d]; 6850 } else { 6851 PetscFV fv = (PetscFV) obj; 6852 6853 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 6854 numDof[f*(dim+1)+dim] = numComp[f]; 6855 } 6856 } 6857 for (f = 0; f < numFields; ++f) { 6858 PetscInt d; 6859 for (d = 1; d < dim; ++d) { 6860 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."); 6861 } 6862 } 6863 ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcComps, bcPoints, NULL, §ion);CHKERRQ(ierr); 6864 for (f = 0; f < numFields; ++f) { 6865 PetscFE fe; 6866 const char *name; 6867 6868 ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 6869 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 6870 ierr = PetscSectionSetFieldName(section, f, name);CHKERRQ(ierr); 6871 } 6872 ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); 6873 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6874 for (bc = 0; bc < numBC; ++bc) {ierr = ISDestroy(&bcPoints[bc]);CHKERRQ(ierr);ierr = ISDestroy(&bcComps[bc]);CHKERRQ(ierr);} 6875 ierr = PetscFree3(bcFields,bcPoints,bcComps);CHKERRQ(ierr); 6876 ierr = PetscFree2(numComp,numDof);CHKERRQ(ierr); 6877 ierr = PetscFree(isFE);CHKERRQ(ierr); 6878 PetscFunctionReturn(0); 6879 } 6880 6881 /*@ 6882 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 6883 6884 Input Parameter: 6885 . dm - The DMPlex object 6886 6887 Output Parameter: 6888 . regular - The flag 6889 6890 Level: intermediate 6891 6892 .seealso: DMPlexSetRegularRefinement() 6893 @*/ 6894 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 6895 { 6896 PetscFunctionBegin; 6897 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6898 PetscValidPointer(regular, 2); 6899 *regular = ((DM_Plex *) dm->data)->regularRefinement; 6900 PetscFunctionReturn(0); 6901 } 6902 6903 /*@ 6904 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 6905 6906 Input Parameters: 6907 + dm - The DMPlex object 6908 - regular - The flag 6909 6910 Level: intermediate 6911 6912 .seealso: DMPlexGetRegularRefinement() 6913 @*/ 6914 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 6915 { 6916 PetscFunctionBegin; 6917 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6918 ((DM_Plex *) dm->data)->regularRefinement = regular; 6919 PetscFunctionReturn(0); 6920 } 6921 6922 /* anchors */ 6923 /*@ 6924 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 6925 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 6926 6927 not collective 6928 6929 Input Parameters: 6930 . dm - The DMPlex object 6931 6932 Output Parameters: 6933 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 6934 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 6935 6936 6937 Level: intermediate 6938 6939 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 6940 @*/ 6941 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 6942 { 6943 DM_Plex *plex = (DM_Plex *)dm->data; 6944 PetscErrorCode ierr; 6945 6946 PetscFunctionBegin; 6947 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6948 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 6949 if (anchorSection) *anchorSection = plex->anchorSection; 6950 if (anchorIS) *anchorIS = plex->anchorIS; 6951 PetscFunctionReturn(0); 6952 } 6953 6954 /*@ 6955 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 6956 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 6957 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 6958 6959 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 6960 DMGetConstraints() and filling in the entries in the constraint matrix. 6961 6962 collective on dm 6963 6964 Input Parameters: 6965 + dm - The DMPlex object 6966 . 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). 6967 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 6968 6969 The reference counts of anchorSection and anchorIS are incremented. 6970 6971 Level: intermediate 6972 6973 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 6974 @*/ 6975 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 6976 { 6977 DM_Plex *plex = (DM_Plex *)dm->data; 6978 PetscMPIInt result; 6979 PetscErrorCode ierr; 6980 6981 PetscFunctionBegin; 6982 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6983 if (anchorSection) { 6984 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 6985 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 6986 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 6987 } 6988 if (anchorIS) { 6989 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 6990 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 6991 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 6992 } 6993 6994 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 6995 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 6996 plex->anchorSection = anchorSection; 6997 6998 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 6999 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 7000 plex->anchorIS = anchorIS; 7001 7002 #if defined(PETSC_USE_DEBUG) 7003 if (anchorIS && anchorSection) { 7004 PetscInt size, a, pStart, pEnd; 7005 const PetscInt *anchors; 7006 7007 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 7008 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 7009 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 7010 for (a = 0; a < size; a++) { 7011 PetscInt p; 7012 7013 p = anchors[a]; 7014 if (p >= pStart && p < pEnd) { 7015 PetscInt dof; 7016 7017 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 7018 if (dof) { 7019 PetscErrorCode ierr2; 7020 7021 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 7022 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 7023 } 7024 } 7025 } 7026 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 7027 } 7028 #endif 7029 /* reset the generic constraints */ 7030 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 7031 PetscFunctionReturn(0); 7032 } 7033 7034 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 7035 { 7036 PetscSection anchorSection; 7037 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 7038 PetscErrorCode ierr; 7039 7040 PetscFunctionBegin; 7041 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7042 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 7043 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 7044 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 7045 if (numFields) { 7046 PetscInt f; 7047 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 7048 7049 for (f = 0; f < numFields; f++) { 7050 PetscInt numComp; 7051 7052 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 7053 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 7054 } 7055 } 7056 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 7057 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 7058 pStart = PetscMax(pStart,sStart); 7059 pEnd = PetscMin(pEnd,sEnd); 7060 pEnd = PetscMax(pStart,pEnd); 7061 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 7062 for (p = pStart; p < pEnd; p++) { 7063 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 7064 if (dof) { 7065 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 7066 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 7067 for (f = 0; f < numFields; f++) { 7068 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 7069 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 7070 } 7071 } 7072 } 7073 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 7074 PetscFunctionReturn(0); 7075 } 7076 7077 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 7078 { 7079 PetscSection aSec; 7080 PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 7081 const PetscInt *anchors; 7082 PetscInt numFields, f; 7083 IS aIS; 7084 PetscErrorCode ierr; 7085 7086 PetscFunctionBegin; 7087 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7088 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 7089 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 7090 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 7091 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 7092 ierr = MatSetType(*cMat,MATSEQAIJ);CHKERRQ(ierr); 7093 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 7094 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 7095 /* cSec will be a subset of aSec and section */ 7096 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 7097 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 7098 i[0] = 0; 7099 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 7100 for (p = pStart; p < pEnd; p++) { 7101 PetscInt rDof, rOff, r; 7102 7103 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 7104 if (!rDof) continue; 7105 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 7106 if (numFields) { 7107 for (f = 0; f < numFields; f++) { 7108 annz = 0; 7109 for (r = 0; r < rDof; r++) { 7110 a = anchors[rOff + r]; 7111 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 7112 annz += aDof; 7113 } 7114 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 7115 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 7116 for (q = 0; q < dof; q++) { 7117 i[off + q + 1] = i[off + q] + annz; 7118 } 7119 } 7120 } 7121 else { 7122 annz = 0; 7123 for (q = 0; q < dof; q++) { 7124 a = anchors[off + q]; 7125 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 7126 annz += aDof; 7127 } 7128 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 7129 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 7130 for (q = 0; q < dof; q++) { 7131 i[off + q + 1] = i[off + q] + annz; 7132 } 7133 } 7134 } 7135 nnz = i[m]; 7136 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 7137 offset = 0; 7138 for (p = pStart; p < pEnd; p++) { 7139 if (numFields) { 7140 for (f = 0; f < numFields; f++) { 7141 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 7142 for (q = 0; q < dof; q++) { 7143 PetscInt rDof, rOff, r; 7144 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 7145 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 7146 for (r = 0; r < rDof; r++) { 7147 PetscInt s; 7148 7149 a = anchors[rOff + r]; 7150 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 7151 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 7152 for (s = 0; s < aDof; s++) { 7153 j[offset++] = aOff + s; 7154 } 7155 } 7156 } 7157 } 7158 } 7159 else { 7160 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 7161 for (q = 0; q < dof; q++) { 7162 PetscInt rDof, rOff, r; 7163 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 7164 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 7165 for (r = 0; r < rDof; r++) { 7166 PetscInt s; 7167 7168 a = anchors[rOff + r]; 7169 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 7170 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 7171 for (s = 0; s < aDof; s++) { 7172 j[offset++] = aOff + s; 7173 } 7174 } 7175 } 7176 } 7177 } 7178 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 7179 ierr = PetscFree(i);CHKERRQ(ierr); 7180 ierr = PetscFree(j);CHKERRQ(ierr); 7181 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7182 PetscFunctionReturn(0); 7183 } 7184 7185 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 7186 { 7187 DM_Plex *plex = (DM_Plex *)dm->data; 7188 PetscSection anchorSection, section, cSec; 7189 Mat cMat; 7190 PetscErrorCode ierr; 7191 7192 PetscFunctionBegin; 7193 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7194 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 7195 if (anchorSection) { 7196 PetscDS ds; 7197 PetscInt nf; 7198 7199 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 7200 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 7201 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 7202 ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 7203 ierr = PetscDSGetNumFields(ds,&nf);CHKERRQ(ierr); 7204 if (nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 7205 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 7206 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 7207 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 7208 } 7209 PetscFunctionReturn(0); 7210 } 7211