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