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